문제출처: https://www.acmicpc.net/problem/1543


풀이

정답률이 예상외로 낮네요.. 아마도 c언어로 구현하는데 문자열을 입력할 때 공백까지 포함해서 입력받는법을 모르셨거나, c++로 구현시 공백을 감안하지않은 분들이 많았기 때문일겁니다. 저는 c++ string 으로 구현하였는데, 문자열입력시 getline함수만 사용하면 쉽게 풀리는 것 같습니다!


코드

#include<iostream>
#include<string>
using namespace std;
int main()
{
	string s1, s2;
	getline(cin, s1);
	getline(cin, s2);
	int cnt = 0;
	if (s1.size() < s2.size())
	{
		cout << 0 << endl;
		return 0;
	}
	for (int i = 0; i <= s1.size()-s2.size();)
	{
		bool check = true;
		for (int j = 0; j < s2.size(); j++)
		{
			if (s1[i + j] != s2[j])
			{
				check = false;
				break;
			}
		}
		if (check)
		{
			cnt++;
			i += s2.size();
		}
		else
			i++;
	}
	cout << cnt << endl;
}


결과





'문제풀이(BOJ) > 문자열' 카테고리의 다른 글

[백준 1296] 데이트  (0) 2020.01.13
[백준 8892] 팰린드롬  (0) 2020.01.10
[백준 11008] 복붙의 달인  (0) 2020.01.10
[백준 12780] 원피스  (0) 2020.01.10
[백준 2535] 아시아 정보올림피아드(클래스 연습)  (0) 2020.01.06

문제출처: https://www.acmicpc.net/problem/1296


풀이

간단한 문자열문제입니다. c언어스타일로 오민식이름에서 L,O,V,E의 갯수 + 입력받는 여자의 이름의 L,O,V,E의 갯수를 합하여 계산값이 가장 크면서 사전순으로 앞에있는 여자의 이름을 출력하면 됩니다. 저는 string으로 풀었습니다.  string으로 풀 때는 모두 입력받고 정렬 시킨뒤 계산하는게 편합니다.


코드

#include<iostream>
#include<algorithm>
#include<string>

using namespace std;
int max_value = -1;
string arr[50];
int main()
{
	int n;
	//L,O,V,E
	string a;
	cin >> a >> n;
	int index = 0;
	for (int i = 0; i < n; i++)
	{
		cin >> arr[i];
	}
	sort(arr, arr + n);
	for(int i=0;i<n;i++)
	{
		string temp = "";
		int l=0, o=0, v=0, e=0;
		temp = a + arr[i];
		for (int i = 0; i < temp.size(); i++)
		{
			if (temp[i] == 'L')
				l++;
			else if (temp[i] == 'O')
				o++;
			else if (temp[i] == 'V')
				v++;
			else if (temp[i] == 'E')
				e++;
		}
		if (max_value < ((l + o) * (l + v) * (l + e) * (o + v) * (o + e) * (v + e)) % 100)
		{
			max_value = ((l + o) * (l + v) * (l + e) * (o + v) * (o + e) * (v + e))%100;
			index = i;
		}
	}
	cout << arr[index]<<endl;
}


결과

문제출처: https://www.acmicpc.net/problem/8892


문제

팰린드롬은 어느 방향으로 읽어도 항상 같은 방법으로 읽을 수 있는 단어이다. 예를 들어, civic, radar, rotor, madam은 팰린드롬이다.

상근이는 단어 k개 적혀있는 공책을 발견했다. 공책의 단어는 ICPC 문제가 저장되어 있는 서버에 접속할 수 있는 비밀번호에 대한 힌트이다. 비밀번호는 k개의 단어 중에서 두 단어를 합쳐야 되고, 팰린드롬이어야 한다. 예를 들어, 단어가 aaba, ba, ababa, bbaa, baaba일 때, ababa와 ba를 합치면 팰린드롬 abababa를 찾을 수 있다.

단어 k개 주어졌을 때, 팰린드롬을 찾는 프로그램을 작성하시오.


입력

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스의 첫째 줄에는 공책에 적혀져있는 단어의 수 k(1 ≤ k ≤ 100)가 주어진다. 다음 k개 줄에는 a부터 z까지 알파벳으로 이루어진 단어가 한 줄에 하나씩 주어진다. 모든 단어 길이의 합은 10,000보다 작거나 같다.


출력

각 테스트 케이스마다 팰린드롬을 출력한다. 만약, 가능한 팰린드롬이 여러 가지라면 아무거나 출력한다. 팰린드롬을 만들 수 없는 경우에는 0을 출력한다.


풀이

string을이용해서 풀었습니다. string 배열에 값을 입력하고, 팰린드롬일때 ,아닐 때 의 값을출력하는 함수, 팰린드롬진위여부 확인함수 2개를 이용합니다. 코드를 보면 이해가 쉬울것이고, 주의해야할 것은 33행과 35행의 변수선언입니다. ba,ababa일때 ba와 ababa만 비교하고 ababa와 ba를 비교하지않으면(예를들어 버블정렬처럼 변수 선언 시) 0이 출력됩니다. 그리고 37행은 같은 문자열은 무조건 팰린트롬이 될 수 없으므로 연산을 건너뛰게해줍니다.


코드

#include<iostream>
#include<string>
using namespace std;
string s[100];
void func1();
bool func2(string x);
int k;
int main()
{
	cin.tie(0); cin.sync_with_stdio(false);
	int t;
	cin >> t;
	while (t--)
	{
		func1();
	}
}
bool func2(string x)
{
	for (int i = 0; i < x.size() / 2; i++)
	{
		if (x[i] != x[x.size() - i - 1])
			return false;
	}
	return true;
}
void func1()
{
	cin >> k;
	for (int i = 0; i < k; i++)
		cin >> s[i];

	for (int i = 0; i < k ; i++)
	{
		for (int j = 0; j < k; j++)
		{
			//i==j면 같은 글자이므로 절대 불가능
			if (i == j)continue;
			//팰린드롬이면
			if (func2(s[i] + s[j]))
			{
				cout << s[i] + s[j] << '\n';
				return;
			}
		}
	}
	//다 비교했는데도 팰린드롬아니면 0출력
	cout << 0 << '\n';
}


결과






문제출처: https://www.acmicpc.net/problem/11008


문제

한신이는 대학교에서 "복붙의 달인"으로 유명하다. 한신이는 타이핑 속도가 느리기 때문에 대학에서 가능한 모든 일을 복붙으로 해결한다. 그는 n개의 문자를 입력하는데 있어서 n초의 시간이 걸리지만 뛰어난 "붙여넣기" 스킬을 이용하면 어떠한 개수의 문자도 단 1초만에 타이핑 할 수 있다. 만약 한신이가 "bana"를 복사한 상태에서 "banana"를 타이핑한다면, "bana" 붙여넣기 1초, 'n' 입력, 'a' 입력으로 총 3초가 걸린다. 한신이가 클립보드에 저장한 p를 알고 있을 때 s를 입력하는데 걸리는 최소 시간을 계산해보자!


입력

첫 번째 줄에는 테스트케이스의 개수 T(T ≤ 25)가 입력된다. 각 테스트케이스는 한 줄에 2개의 문자열 s와 p가 공백으로 구분되어 입력되며 한신이는 p를 복사하여 s를 만들어 내는 것을 목표로 한다. s의 최대 길이는 10,000이고, p의 최대 길이는 100이다.


출력

각 테스트 케이스에 맞는 한신이가 p를 이용하여 s를 타이핑할 때 걸리는 최소 시간(초 단위)을 출력하라!


풀이

string에 부분문자열을 구할 수 있는 substr기능으로 쉽게 풀 수 있습니다. 정답을 구하기위해선 일단 비교연산을 최대 s.size()만큼 해야하겠죠?(15행) 그리고 18행을 보면, s의 현재인덱스~p.size()만큼의 문자열이 p라면 start변수에 p.size()만큼 더해야합니다.(복붙하고 다시 또 복붙할게있나 확인하는연산), 아니라면 start를 한칸 옮겨주면서 다시 비교합니다. 한번 비교를 끝내고 연산 횟수를 카운팅해주며 최소횟수를 출력하면됩니다.




코드

#include<iostream>
#include<string>
using namespace std;
int main()
{
	int t;
	cin >> t;
	string s, p;
	for (int i = 0; i < t; i++)
	{
		int ans = 0;
		cin >> s >> p;
		int start = 0;
		//최대 s크기만큼연산
		while (start<s.size())
		{
			//s의 현재 부분문자열이 p면
			if (s.substr(start, p.size()) == p)
				//p사이즈만큼 건너뜀
				start += p.size();
			//아니면,start를한칸 옮김
			else
				start++;
			//연산한번 하고나서 한번씩카운팅
			ans++;
		}
		cout << ans << endl;
	}
}


결과

문제출처: https://www.acmicpc.net/problem/12780


문제

바야흐로 지금은 대해적 시대, 밀짚모자 해적단의 선장 교정이는 어린 시절 우연히 잊지 못할 한 마디를 들었다. 그것은 바로 해적 왕 골.D.상윤이 자신이 모은 모든 보물인 원피스를 위대한 항로에 놓고 왔다는 것이었다. 원피스를 가진 자는 이 세상을 가질 수 있다는 매혹적인 얘기였다.

모두들 말도 안 된다고 고개를 저었지만 교정이는 동료를 모아 원피스를 찾아 여행을 떠났다. 하늘섬을 지나 어인섬도 지나고 사황을 무너뜨린 뒤 교정이와 동료들은 결국 원피스의 위치가 적힌 결정적인 단서를 찾아냈다. 이 단서는 한 눈에 봐서는 해독이 어려웠다. 왜냐하면 여기에는 그저 알파벳 대문자들이 연속해서 적혀있었기 때문이다.

하지만 천재적인 두뇌를 가진 교정이의 동료이자 해적단의 항해사 진아는 단번에 이 단서에 어떤 특정 문자열이 여러 번 등장한다는 것을 직감했다.

이 특정 문자열이 어떤 문자열인지는 잘 알 수 없었던 진아는 자신이 생각한 모든 문자열이 이 단서에서 총 몇 번 등장하는지 알아보기로 했다. 아마도 가장 많이 등장한 문자열이 원피스의 위치를 알려줄 것이라고 생각했기 때문이다.

진아는 밀짚모자 해적단의 프로그래밍 담당인 당신에게 도움을 요청했다. 단서 전체에 진아가 원하는 문자열이 몇 번 등장하는지 알아내는 프로그램을 작성하라.


입력

입력의 첫 줄에는 해적단이 획득한 단서의 문자열 H가 주어진다.(0 < |H| ≤ 100,000)

입력의 두 번째 줄에는 진아가 H에서 등장 횟수를 알고 싶은 문자열 N이 주어진다.(0 < |N| ≤ 10)

단, N과 H는 공백 없는 문자열로 주어지며, 모두 알파벳 대문자로 이루어져 있다.


출력

H에서 N이 몇 번 등장하는지 출력한다.


풀이

이런 "A문자열에서 B문자열이 몇번나오냐?" 문제를 효율적으로 풀 수 있는 KMP알고리즘이있습니다. 

아래의 저의 풀이는 O(N*M)이지만, KMP알고리즘을이용한 풀이는 무려 O(N+M)입니다.. 그런데 아직 제가 KMP알고리즘을 몰라서 다음에 다시 이 방법으로 풀어보려합니다.(알고계시면 좋을 것 같아서..)

제 풀이 중 어려운 것은 없지만 A와 B를 비교 하기위해 12행의 조건식을 사용한것을 이해하셔야합니다.  이렇게 일일이 비교하는것입니다. 

그리고 19~22행은 B문자열이 A에없을 때 빠져나오는과정입니다. 28행에서 check가 true면 해당 문자열이 A에 있는것이므로 카운팅해줍니다.


코드

#include<iostream>
#include<string>
using namespace std;
int main()
{
	int t;
	string s, p;
		//횟수
		int cnt = 0;
		cin >> s >> p;
		//정확히 s.size()-p.size()+1번 비교함
		for (int i = 0; i<s.size() - p.size() + 1; i++)
		{
			//문자열이 있는지 확인하는 변수
			bool check = true;
			for (int j = 0; j < p.size(); j++)
			{
				//없으면
				if (s[i + j] != p[j])
				{
					check = false;
					break;
				}
			}
			//true면 B가 A에 존재하는거임.
			if (check)cnt++;
		}
		cout << cnt << endl;
}


결과

문제출처: https://www.acmicpc.net/problem/2535


문제

최근 아시아 지역의 학생들만 참여하는 정보 올림피아드 대회가 만들어졌다. 이 대회는 온라인으로 치러지기 때문에 각 나라에서 이 대회에 참여하는 학생 수의 제한은 없다. 

참여한 학생들의 성적순서대로 세 명에게만 금, 은, 동메달을 수여한다. 단, 동점자는 없다고 가정한다. 그리고 나라별 메달 수는 최대 두 개다.

예를 들어, 대회 결과가 다음의 표와 같이 주어졌다고 하자.

이 경우, 금메달 수상자는 1번 국가의 1번 학생이고, 은메달 수상자는 1번 국가의 2번 학생이며, 동메달 수상자는 3번 국가의 4번 학생이다. (1번 국가의 3번 학생의 성적이 동메달 수여자보다 높지만, 나라 별 메달 수가 두 개 이하 이므로 1번 국가 3번 학생은 동메달을 받을 수 없다.)

대회 결과가 입력으로 주어질 때, 메달 수상자를 결정하여 출력하는 프로그램을 작성하시오.


입력

첫 번째 줄에는 대회참가 학생 수를 나타내는 N이 주어진다. 단, 3<=N<=100이다. 두 번째 줄부터 N개의 줄에는 각 줄마다 한 학생의 소속 국가 번호, 학생 번호, 그리고 성적이 하나의 빈칸을 사이에 두고 주어진다. 단, 국가 번호는 1부터 순서대로 하나의 정수로 주어지며, 각 학생번호는 각 나라별로 1부터 순서대로 하나의 정수로 주어진다, 점수는 0 이상 1000 이하의 정수이고, 동점자는 없다고 가정한다. 입력으로 제공되는 국가는 적어도 두 나라 이상이다.


출력

메달을 받는 학생들을 금, 은, 동메달 순서대로 한 줄에 한 명씩 출력한다. 즉, 첫 번째 줄에는 금메달 수상자를, 두 번째 줄에는 은메달 수상자를, 세 번째 줄에는 동메달 수상자를 출력한다. 하나의 줄에는 소속국가 번호와 학생 번호를 하나의 빈칸을 사이에 두고 출력한다. 


풀이

구조체+정렬 문제로써, c언어 구조체스타일로 구현할 수 있지만 이럴 때 클래스를 안쓰면 나중에 까먹을까봐 클래스로 구현했습니다.

25행까지는 무리없이 이해가 가실거고, 같은나라에서 두개의 메달이나왔을 때 세번째 메달의 순위를 구하는 방법을 알아봅시다.

방법은 간단합니다. 학생 수가 3~100까지므로 학생이속한 나라의 메달 갯수를 저장하기위해 100크기의 1차원배열을 선언합니다.

그리고 42행을 보면, 보기의 예시처럼 1번국가에서 3개의 메달이 나오는것을 방지하기위해 한 국가에서 메달이 2개까지나왔는지를 검사합니다.

참이면 1증가시켜주고 동메달의 점수를 갖는 사람의 국가가 그 국가일 때 건너뛸 수있도록합니다. 그리고 그 연산을 마치고 cnt를 증가시켜주며 3명까지 출력 시킬 수 있도록합니다!


코드

#include<iostream>
#include<algorithm>
using namespace std;
class info
{
public:
	int born;
	int num;
	int score;
	info() {}
	void setInfo(int born, int num, int score)
	{
		this->born = born;
		this->num = num;
		this->score = score;
	}
	void showInofo()
	{
		cout << this->born << " " << this->num << endl;
	}
	bool operator<(const info&stu) const
	{
		return this->score >stu.score;
	}
};
int check[100];
using namespace std;
int main()
{
	info stu[100];
	int born, num, score;
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		cin >> born >> num >> score;
		stu[i].setInfo(born, num, score);
	}
	sort(stu, stu + n);
	for (int i = 0,cnt=0; i < n&&cnt<3; i++)
	{
		if (check[stu[i].born] < 2) {
			check[stu[i].born]++;
			stu[i].showInofo();
			cnt++;
		}
	}
}


결과



'문제풀이(BOJ) > 문자열' 카테고리의 다른 글

[백준 11008] 복붙의 달인  (0) 2020.01.10
[백준 12780] 원피스  (0) 2020.01.10
[백준 1075] 나누기(string연습!!)  (0) 2020.01.06
[백준 3181] 줄임말 만들기  (0) 2020.01.02
[백준 9226] 도깨비말  (0) 2019.12.06

문제출처: https://www.acmicpc.net/problem/1075


제목에도 나와있듯이  c++ string기능들을 익히기위해 string 으로 풀어봤습니다.

물론, 문제의 조건을 이용해서 숫자로 푸는게 제일 깔끔하고 코드가 짧습니다. (충분히 푸실 수 있으니 풀이는 생략)

저는 stirng 사용법을 익히고자 아래와 같은 방법으로 풀어보았습니다.


string 사용이 아직 미숙하시면 아래의 링크를 참고해주세요!!

stirng사용법 부수기 : https://jow1025.tistory.com/51


문제

두 정수 N과 F가 주어진다. 지민이는 정수 N의 가장 뒤 두 자리를 적절히 바꿔서 N을 F로 나누어 떨어지게 만들려고 한다. 만약 가능한 것이 여러 가지이면, 뒤 두 자리를 가능하면 작게 만들려고 한다.

예를 들어, N=275이고, F=5이면, 답은 00이다. 200이 5로 나누어 떨어지기 때문이다. N=1021이고, F=11이면, 정답은 01인데, 1001이 11로 나누어 떨어지기 때문이다.


입력

첫째 줄에 N, 둘째 줄에 F가 주어진다. N은 100보다 크거나 같고, 2,000,000,000보다 작거나 같은 자연수이다. F는 100보다 작거나 같은 자연수이다.


출력

첫째 줄에 마지막 두 자리를 모두 출력한다. 한자리이면 앞에 0을 추가해서 두 자리로 만들어야 한다.


풀이

코드로 확인하는게 이해가 더 편할 것 같습니다.

말그대로 string사용법을 익히기위한 풀이방식입니다. (이렇게 풀지마세요..굳이...)


코드

#include<iostream>
#include<string>
using namespace std;
int main()
{
	int n, f;
	cin >> n >> f;
	string s = to_string(n);
	//맨 뒤, 맨 뒤-1자릿값 x,y에 저장
	int x = s[s.size() - 1]-'0';
	int y = s[s.size() - 2]-'0';
	//뒤 두자리 뺀 값을 저장
	string temp1 = s.substr(0, s.size() - 2);
	//0부터 하나씩 다 찾아보다가 찾으면 출력
	for (int i = 0; i <= 9; i++)
	{
		for (int j = 0; j <= 9; j++)
		{
			//temp1에 0~9값을 추가해가며 f로나눠지는지확인
			int temp2=stoi(temp1 + to_string(i)+to_string(j));
			if (temp2 % f == 0)
			{
				cout << i << j;
				return 0;
			}
		}
	}
}


결과

문제출처: https://www.acmicpc.net/problem/3181


문제

꿍은 만사가 귀찮아서 말을 하기도 귀찮아 한다. 그래서 하려는 말을 대신해줄 줄임말을 만들려고 하는데 나름 규칙을 만들었다.

하려는 말은 최소 하나 이상의 단어를 포함하는데 각 단어들은 정확히 한칸의 공백으로 구분이 된다. 줄임말을 만들때는 각 단어의 앞글자를 따서 만들어지는데 다음의 단어들은 쓸모없는 단어들이므로 무시한다.

'i', 'pa', 'te', 'ni', 'niti', 'a', 'ali', 'nego', 'no', 'ili'.

하지만 이 단어들이 하려는 말의 맨 앞에 올경우 매우 중요하다고 판단되어 무시하면 안되고 줄임말에 포함하여야 한다.

줄임말을 만들기도 귀찮아진 꿍을 위해 줄임말을 만들어주는 프로그램을 작성하라.

단, 줄임말은 모두 대문자로만 이루어져있다. 


입력

입력은 유일하게 한 줄만 주어지며 하려는 말이 포함되어 있다.

문장은 알파벳 소문자와 공백으로만 이루어져 있다.

문장의 최대길이는 100이다.


출력

만들어진 줄임말을 출력하라.


풀이

vector는 동적배열, vector가 담은 내부 요소는 정적배열로 이루어져있다는 것을 알면 vector,string으로 풀 수 있습니다. 아래 소스코드에서도 어느정도 알 수 있지만 vector<string>v 에서 v[0][0]은 0번째 벡터의, 0번째 벡터가담은 <string>의 첫번째 요소를 나타냅니다. 예를들어 0번째 벡터v에 abc가 담겨있다면 v[0][2]는 c가 되겠죠? 즉,2차원배열처럼 사용한다고 생각하면 이해가 쉽습니다. (백준사이트에 사용법을 문의해봤습니다.) 

문제로 돌아가서, 벡터에 따옴표로 구분되는 문자열을 삽입하기위해 임시변수temp로 문자열을 넣어줍니다. 그리고 소스코드에도 나와있듯이 null문자를만나기전의 마지막 문자열을 삽입해야하므로 22행을 꼭 실행해야합니다. 그러고나서 첫번째 글자를 출력하고 그다음부터는(2번째문자부터) 조건에맞게 출력하면됩니다.


코드

#include<iostream>
#include<vector>
#include<string>
using namespace std;
int main()
{
	string word;
	getline(cin, word);
	string temp;
	vector<string>v;
	for (int i = 0; i < word.size(); i++)
	{
		if (word[i] == ' ')
		{
			v.push_back(temp);
			temp = "";
		}
		else
			temp += word[i];
	}
	//마지막 null전까지의 단어까지넣고,
	v.push_back(temp);
	//최소하나의단어를포함하므로 첫글자출력
	cout << char(v[0][0]-'a'+'A');
	for (int i = 1; i < v.size(); i++)
	{
		if (v[i] != "i" && v[i] != "pa" && v[i] != "te" && v[i] != "ni" && v[i] != "niti" && v[i] != "a" && v[i] != "ali" && v[i] != "nego" && v[i] != "no" && v[i] != "ili")
			cout << char(v[i][0] - 'a' + 'A');
	}
	cout << endl;
	
}


결과

+ Recent posts