【题解】Codeforces126B. Password 前缀函数(KMP)

给一个字符串 S ( 1 e 6 ) S(1e6) ,求它的一个最长的子串 t t ,满足 t t 既是 S S 的前缀,又是 S S 的后缀,又在一个既不是前缀又不是后缀的地方出现。

如果没有这样的子串,输出Just a legend.


性质很强,解法很多。

比如求得前缀函数,然后从大到小遍历整个字符串的所有候选border,看有没有一个位置的前缀函数值等于这个候选border.(实际上从第二个开始一定有).


  1. WA一次,因为我检查候选border的方式写成了cnt>1。但实际上cnt=1是可行的,因为这个候选border并一定不会在整个字符串的前缀函数里出现。
  2. 这个题需要对前缀函数的性质有很好的了解,适合kmp算法的掌握测试。
/* LittleFall : Hello! */
#include <bits/stdc++.h>
using namespace std; using ll = long long; inline int read();
const int M = 1000016, MOD = 1000000007;

char str[M];
int fail[M], cnt[M];
int main(void)
{
	#ifdef _LITTLEFALL_
	freopen("in.txt","r",stdin);
    #endif

	scanf("%s",str);
	int n = strlen(str);
	for(int i=1, j=0; str[i]; ++i)
	{
		while(j && str[i]!=str[j]) j=fail[j-1];
		fail[i] = str[i]==str[j] ? ++j : 0;
		cnt[fail[i]]++;
	}
	int j = fail[n-1]; 
	if(cnt[j]==1) j = fail[j-1];
	printf("%s\n", j ? str+n-j : "Just a legend" );



    return 0;
}


inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
发布了375 篇原创文章 · 获赞 305 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/m0_37809890/article/details/103045285