codeforces 126B Password KMP

来源:互联网 发布:windows 微软雅黑字体 编辑:程序博客网 时间:2024/05/19 18:42

          给一个串,求一个最长子串同时是母串的前缀,后缀,并且在前缀后缀之外有出现了一次。

          首先构造好失配函数,从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;}


0 0
原创粉丝点击