Codeforces126B

题目大意

给定一个字符串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
");
    else
    {
        getfail(s,strlen(s));
        strncpy(T,s+1,strlen(s)-2);
        T[strlen(s)-2]='';
        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
"); 
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zjbztianya/p/3330861.html