KMP(4)--poj2752(next数组的应用)

 Seek the Name, Seek the Fame

Time Limit: 2000 MS     Memory Limit: 65536 KB     64bit IO Format: %lld & %llu

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

       

       这道题给定一个字符串s,从小到大输出s中既是前缀又是后缀的子串的长度。(包括它本身)
此题非常简单,借用KMP算法的next数组,设s的长度为n,则s串本身必定满足条件。其他满足条件的子串都有个特征,就是该子串的最后一个字符肯定与s的最后一个字符相同。这正是next数组发挥作用的时候。从n - 1位既最后一位开始回滚,若s[next[n-1]] == s[n-1],则子串s[0,1,2,...,next[n-1]]是满足条件的子串。然后判断s[next[next[n-1]]] == s[n-1]是否成立,这样一直回滚,直到next[next[.....next[n-1]]] == -1为止。把答案从大到小存下来,再从小到大输出即可。

      上面说得有点抽象,就如题目中的例子原串=ababcababababcabab,next=0 1 1 2 3 1 2 3 4 5 4 5 4 5 6 7 8 9 10
我们知道next【19】=10,意思也就是说你当前的字符串与原串在第19个字符不同了,你下一次跳到你要比较的字符串的第10位和原串
的第19位进行比较,根据next数组的定义,也就是说前缀的9个字符和后缀的9个是一样的所以直接让你的串的第10个和原串的19位相比较
而next【10】=5,也就是说你已经比较完了前四个,直接第五个和19位比较,下面的一致类推。
next数组想法很犀利啊……

 来一串犀利的代码......

#include<stdio.h>
#include<string.h>
int next[400005];
char str[400005];
void GetNextval(){
	int i=0;
	int j=-1;
	next[0]=-1;
	int len=strlen(str);
	while(i<len){
		if(j==-1||str[i]==str[j]){
			next[++i]=++j;
		}
		else j=next[j];
	}
}
void Print(int i){             //递归地输出next数组的值
	if(next[i]<=0)return;
	Print(next[i]);
	printf("%d ",next[i]);
}
int main()
{
	while(scanf("%s",str)!=EOF){
		GetNextval();
		Print(strlen(str));
		printf("%d\n",strlen(str));      //由于包括它本身,所以最后要输出它本身的长度
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值