POJ 2752 Seek the Name, Seek the Fame(字符串前缀后缀,KMP算法应用)

题目来源:http://poj.org/problem?id=2752

Seek the Name, Seek the Fame

Time Limit: 2000MS

 

Memory Limit: 65536K

Total Submissions: 24318

 

Accepted: 12673

Description

The little cat is so famous, that many couples tramp over hill and dale to Byteland, and asked the little cat to give names to their newly-born babies. They seek the name, and at the same time seek the fame. In order to escape from such boring job, the innovative little cat works out an easy but fantastic algorithm: 

Step1. Connect the father's name and the mother's name, to a new string S. 
Step2. Find a proper prefix-suffix string of S (which is not only the prefix, but also the suffix of S). 

Example: Father='ala', Mother='la', we have S = 'ala'+'la' = 'alala'. Potential prefix-suffix strings of S are {'a', 'ala', 'alala'}. Given the string S, could you help the little cat to write a program to calculate the length of possible prefix-suffix strings of S? (He might thank you by giving your baby a name:) 

Input

The input contains a number of test cases. Each test case occupies a single line that contains the string S described above. 

Restrictions: Only lowercase letters may appear in the input. 1 <= Length of S <= 400000. 

Output

For each test case, output a single line with integer numbers in increasing order, denoting the possible length of the new baby's name.

Sample Input

ababcababababcabab
aaaaa

Sample Output

2 4 9 18
1 2 3 4 5

------------------------------------------------------------

题意

求字符串中各个公共前缀后缀(这题的前缀/后缀可以是字符串自身)的长度。例如”ababcababababcabab”的公共前缀后缀有:它自身以及”ababcaba”,”abab”,”ab”。

------------------------------------------------------------

思路

如果直接遍历整个字符串逐一判断前缀后缀是否一致,则遇到形如”aaaaa”的字符串时复杂度为O(n^2).

定义1:一个字符串所有公共前缀后缀(不含自身)中长度最长的公共前缀后缀成为“最大前缀后缀”。例如”ababcababababcabab”的最大公共前缀后缀是”ababcaba”

性质1:字符串的某个公共前缀后缀的公共前缀后缀也是该字符串的公共前缀后缀。

根据“性质1”,求一个字符串s(长度为n)的所有公共前缀后缀,只要找到它的最大公共前缀后缀s1,再找到s1的最大公共前缀后缀s2,……如此下去直到sn的最大公共前缀后缀为空字符串。这个过程复杂度为O(n).

于是问题转化为如何求一系列s[0:i](i=0,1,2,…,n-1)的最大公共前缀后缀。KMP算法中求next数组的函数就是解决这一问题的,其思想类似动态规划,复杂度为O(n),详见上一篇博文,在此就不赘述了。

--------------------提醒自己---------------------

一个好习惯,在for/while循环外先把循环条件里的strlen计算出来,不要在循环判断里每次计算(一开始TLE就是这个原因o(╥﹏╥)o)

------------------------------------------------------------

代码

#include<cstdio>
#include<cstring>
#include<algorithm>

const int NMAX = 400005;
char str[NMAX] = {};
int next[NMAX] = {};
int ans[NMAX] = {};

void cal_next()				// next[i]: str[0:(i-1)]的最大公共前缀后缀长度, 动态规划求next数组,O(n)
{
	next[0] = -1;
	int i = -1, j = 0, len = strlen(str);
	while (j < len)
	{
		if (i == -1 || str[i] == str[j])
		{
			next[++j] = ++i;
		}
		else
		{
			i = next[i];
		}
	}
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen("2752.txt","r",stdin);
#endif
	int i = 0, cnt = 0;
	while (scanf("%s", str) != EOF)
	{
		cal_next();
		i = strlen(str);
		cnt = 0;
		while (i > 0)
		{
			ans[cnt++] = i;
			i = next[i];		// next数组回溯找最大前缀后缀的最大前缀后缀
		}
		for (i=cnt-1; i>=0; i--)
		{
			printf("%d ", ans[i]);
		}
		printf("\n");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/da_kao_la/article/details/82315402