您的位置:首页 > 其它

codeforces 126B Password KMP

2014-03-10 20:43 323 查看
          给一个串,求一个最长子串同时是母串的前缀,后缀,并且在前缀后缀之外有出现了一次。

          首先构造好失配函数,从len开始沿失配路径走一遍并且标记沿途节点,为什么要标记,因为如果节点i在这条失配路径上,那么f[i]---i这个子串一定同时为母串的前缀和后缀,之后我们只要从len-1(排除后缀)到0枚举一边,在已标记的节点中找一个最大值就行。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long ll;
const int maxn=1010000;
bool ok[maxn];
int f[maxn];
char s[maxn],ss[maxn];
void getFail(char* P,int* f)
{
int m=strlen(P);
f[0]=0;
f[1]=0;
for (int i=1; i<m; i++)
{
int j=f[i];
while(j && P[i]!=P[j]) j=f[j];
f[i+1]=P[i]==P[j]?j+1:0;
}
}
bool find(char* T,char* P,int* f)
{
int n=strlen(T);
int m=strlen(P);
// getFail(P,f);
int j=0;
for (int i=0; i<n; i++)
{
while(j && P[j]!=T[i]) j=f[j];
if (P[j]==T[i]) j++;
if (j==m) return true;
}
return false;
}

int main()
{
// freopen("in.txt","r",stdin);
while(~scanf("%s",&s))
{

getFail(s,f);
int p=strlen(s);
int l=p;
int cnt=0;
// for (int i=0; i<=l; i++)
// cout<<f[i]<<" ";
// cout<<endl;
memset(ok,false,sizeof ok);
while(p)
{
ok[f[p]]=true;
p=f[p];
}
for (int i=l-1; i>0; i--)
{
if (ok[f[i]]) cnt=max(cnt,f[i]);
}
if (cnt)
{
for (int i=0; i<cnt; i++)
printf("%c",s[i]);
puts("");
}
else
puts("Just a legend");
}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: