본문 바로가기

Algorithm

백준 13506번 카멜레온 부분 문자열

반응형

문제

문자열 S의 부분 문자열 T 중에서, 접두사(Prefix)도 될 수 있고, 접미사(Prefix)도 될 수 있고, 두 경우가 아닌 위치에도 등장하는 T를 카멜레온 부분 문자열이라고 한다.

문자열 S가 주어졌을 때, 카멜레온 부분 문자열을 구하는 프로그램을 작성하시오.

예를 들어, S = "fixprefixsuffix"와 같은 경우에는 "fix"는 접두사, 접미사도 되고, 두 경우가 아닌 위치에도 등장하는 부분 문자열로도 등장한다.

입력

첫째 줄에 문자열 S가 주어진다. S는 알파벳 소문자로만 이루어져있으며, 길이는 106을 넘지 않는 자연수이다.

출력

가능한 카멜레온 부분 문자열 T 중에서 길이가 가장 긴 것을 출력한다. 만약, T가 존재하지 않으면 -1을 출력한다.

KMP 응용의 끝판 같은 느낌.

 

1. 접두어와 접미어의 일치를 구하기 위해 KMP 실패 함수를 통해 최장 일치 접미어를 구한다.

2. 접두어와 접미어가 둘다 아닌 경우를 제외하기 위해 맨 첫글자와 마지막 글자를 제외한 비교의 대상 문자열을 추출한다.

3.최장 접미어로부터 앞글자를 하나씩 줄여가면서 부분 문자열로 존재하는지 확인하는데, 이때 앞글자를 줄인 접미어가 

접두어와 일치하는지 계산해야한다. (즉 이 문자열이 접두어로써도 존재해야함)

4. 일치하면 그 문자열 출력 , 끝까지 일치하는 것이 없다면 -1 출력

 

#include<iostream>
#include<string.h>
#include<vector>
#include<algorithm>

using namespace std;

vector<int> makeTable(string str)
{
	int size = str.size();
	vector<int> table(size, 0);
	int j = 0;
	for (int i = 1; i < size; i++)
	{
		while (j > 0 && str[i] != str[j])
		{
			j = table[j - 1];
		}
		if (str[i] == str[j])
		{
			table[i] = ++j;
		}
	}
	return table;
}

bool KMP(string parent, string pattern)
{
	int parentSize = parent.size();
	int patternSize = pattern.size();

	vector<int> table = makeTable(pattern);
	int j = 0;
	for (int i = 0; i < parentSize; i++)
	{
		while (j > 0 && parent[i] != pattern[j])
		{
			j = table[j - 1];
		}
		if (parent[i] == pattern[j])
		{
			if (j == patternSize - 1)
			{
				return true;
			}
			else
			{
				j++;
			}
		}
	}
	return false;
}

int main()
{
	
	string str;
	cin >> str;
	
	if (str.size() <= 2)
	{
		cout << -1 << endl;
		return 0;
	}

	vector<int> table = makeTable(str);


	string pattern = str.substr(str.size() - table[table.size() - 1], table[table.size() - 1]);
	string parent = str.substr(1,str.size()-2);

	for (int i = 0; i < pattern.size(); i++)
	{
		string str2 = pattern.substr(i, pattern.size() - i);
		string temp = str.substr(0, pattern.size() - i);
		if (str2 == temp && KMP(parent, str2))
		{
			cout << str2 << endl;
			return 0;
		}
		
	}
	cout << -1 << endl;
	return 0;//정상종료시 반드시 0을 리턴해야합니다.
}
반응형

'Algorithm' 카테고리의 다른 글

백준 11404번 플로이드  (0) 2020.08.11
백준 13576번 Prefix와 Suffix  (0) 2020.08.11
백준 11048번 이동하기  (0) 2020.08.10
백준 15989번 1, 2, 3 더하기 4  (0) 2020.08.10
4070. [Professional] 타일링  (0) 2020.08.07