Codeforces126B - Password(KMP)
题目大意
给定一个字符串S,要求你找到一个最长的子串,它既是S的前缀,也是S的后缀,并且在S的内部也出现过(非端点)
题解
KMP的失配函数f[i]的非零值就是前i个字符的一个最长前缀且也是后缀的字符串的末尾位置,倒过来求每一个f[i],并且判断是否在S的内部是否出现即可
代码:
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> using namespace std; #define MAXN 1000005 char T[MAXN],s[MAXN]; int f[MAXN]; void getfail(char *p,int len) { int j; f[0]=j=-1; for(int i=1;i<len;i++) { while(j>=0&&p[j+1]!=p[i]) j=f[j]; if(p[j+1]==p[i]) j++; f[i]=j; } } int find(char *s,int len) { int x=strlen(T); int j=-1; for(int i=0;i<x;i++) { while(j>=0&&s[j+1]!=T[i]) j=f[j]; if(s[j+1]==T[i]) j++; if(j+1==len) return len; } return -1; } int main() { int pp=-1; scanf("%s",s); if(strlen(s)<=2) printf("Just a legend\n"); else { getfail(s,strlen(s)); strncpy(T,s+1,strlen(s)-2); T[strlen(s)-2]='\0'; int j=strlen(s)-1; while(f[j]>=0) { if(f[j]+1>pp) { int t=find(s,f[j]+1); if(t>pp)pp=t; } j=f[j]; } if(pp!=-1) for(int i=0;i<pp;i++) printf("%c",s[i]); else printf("Just a legend\n"); } return 0; }