字符串的前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串;后缀是指不包含第一个字符的所有以最后一个字符结尾的连续子串。例如对于字符串 abacaba
,其前缀有 a
, ab
, aba
, abac
, abacab
,后缀有bacaba
, acaba
, caba
, aba
, ba
, a
。最长公共前后缀就是 aba
。现给出一个长度为 N 的字符串 S,对于每个 M (0<=M<N),求出连续子串 S[0..M] 的最长公共前后缀。
输入格式:
输入数据仅有一行,包含一个长度不超过 100,000 的仅由字母 a-z 构成的字符串。
输出格式:
对于每个 M (0,1,2,...,N−1),输出对应的最长公共前后缀长度,以空格分隔,且行尾不得有多余空格。
输入样例:
abcdabcdabce
输出样例:
0 0 0 0 1 2 3 4 5 6 7 0
题意:给定一行字符串,然后对其所有的连续子串,从0下标开始到len-1下标 ,求其最长相等的前后缀的长度。
思路:刚好符合kmp算法中next【】的定义,即next【i】即表示子串长度为i+1,s【0.....i】这个子串的最长相等前后缀所对应的最大的k,而k+1正好是最长相等前后缀的长度。
#include<cstdio>
#include<cstring>
const int maxn=100010;
int next[maxn]={0};
void getNext(char s[],int len){
int j=-1;
next[0]=-1;
for(int i=1;i<len;i++){
while(j!=-1&&s[i]!=s[j+1]){
j=next[j];
}//当往前找的时候,采用每次让j等于next【j】的方法要方便的多
if(s[i]==s[j+1]){
j++;
}//当新增加的一项 可以满足 相等,则可在上次求得的j的基础上+1就行
next[i]=j;
}
}
int main(){
char s[maxn];
gets(s);
int len=strlen(s);
getNext(s,len);
for(int i=0;i<len;i++){
if(i) putchar(' ');
printf("%d",next[i]+1);
}
}