「水」悠悠碧波

思路: K M P KMP KMP的应用。

这里先复习一波求前后缀表的过程。
首先初始化 f [ 1 ] = 0 f[1]=0 f[1]=0,显然长度为 1 1 1的串没有前后缀。
然后从 i = 2 i=2 i=2开始遍历,每次求出 f [ i ] f[i] f[i],令 j j j表示当前匹配的最大前后缀长度和已经匹配的前缀的最后一个下标。然后每次找到匹配的最大长度,然后特判一下 s [ i ] s[i] s[i]是否等于 s [ j + 1 ] s[j+1] s[j+1],如果是长度加1赋值,否则直接赋值。

这里附上之前写的代码:

前后缀表和字符串下标都从1开始 :

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int p[N];
void kmp(char *s){  //前后缀表和字符串下标都从1开始 
	int l=strlen(s+1),j=0;
	p[1]=0;					//p[1]=0显然,一个字符没有前后缀 
	for(int i=2;i<=l;i++)			//计算p[1]到p[l]  j表示最大前后缀长度和当前匹配的后缀最后一个下标 
	{ 						//i为当前匹配的最后一个下标. 
		while(j&&s[j+1]!=s[i]) j=p[j];//退回到前一个字符的最大前后缀 
		if(s[i]==s[j+1]) j++;//如果相等 长度加1 
		p[i]=j;
	}
}
int main(){
	char s[1005]; 
	memset(p,0,sizeof p); 
	while(cin>>(s+1)){
		kmp(s);
		int l=strlen(s+1);
		for(int i=1;i<=l;i++)
		{
			printf("从1到%d的子串中最大前后缀长度为%d\n",i,p[i]);
		}
	}
	return 0;
} 

前后缀表和字符串下标都从0开始 :

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int p[N];
void kmp(string s){  //前后缀表和字符串下标都从0开始 
	int l=s.size(),j=0;//p[0]=0显然,一个字符没有前后缀 
	for(int i=1;i<l;i++)//计算p[1]到p[l-1]  j表示最大前后缀长度和当前匹配后缀待匹配的最后一个下标 
	{ //i为当前匹配的最后一个下标. 
		while(j&&s[j]!=s[i]) j=p[j-1];//退回到前一个字符的最大前后缀 
		if(s[i]==s[j]) j++;//如果相等 长度加1 
		p[i]=j;
	}
}
int main(){
	string s;
	memset(p,0,sizeof p); 
	while(cin>>s){
		kmp(s);
		for(int i=0;i<s.size();i++)
		{
			printf("从0到%d的子串中最大前后缀长度为%d\n",i,p[i]);
		}
	}
	return 0;
} 

注意下标不同 写法的区别。

对于此题。

显然我们可以标记 1 , n − 1 1,n-1 1,n1的最长公共前后缀表。

然后从长度 f [ n ] f[n] f[n]开始判断,如果出现过,说明 s s s除了是前后缀外,还出现过一次,直接输出。否则从 l e n = f [ l e n ] len=f[len] len=f[len],因为必须是原串前缀串的前后缀才能继续匹配。

时间复杂度: O ( n ) O(n) O(n)

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
int f[N],j,n,vis[N];
char a[N];
int main(){
    f[1]=0;
    cin>>(a+1);
    n=strlen(a+1);
    for(int i=2;i<=n;i++)
    {
        while(j&&a[i]!=a[j+1]) j=f[j];
        if(a[i]==a[j+1]) j++;
        f[i]=j;
    }
    for(int i=1;i<n;i++) vis[f[i]]=1;
    int len=f[n];
    while(len>0){
        if(vis[len]){
            for(int i=1;i<=len;i++)
                printf("%c",a[i]);
            return 0;
        }
        else len=f[len];
    }
    return 0;
}