hdu4763 Theme Section KMP

     给一个字符串S,问是否存在一个子串s'同时为s的前缀,后缀,并且至少出现在前缀后缀之外的位置一次(互不重叠)。10^6的数据...一开始想写后缀数组,看这数据估计是要卡倍增,DC3又没写过..后来想了想直接KMP扫一遍好像就行..以末尾为起点,遍历从失配路径上的每一个点,如果f[j]小于len/3,那么就从2*f[j]+1~len-f[len] 之间枚举k看是否存在f[k]==f[j],存在的话答案就是f[j]。 刚开始我是从f[j]+1开始枚举的,但是遇到aaaabkaa的时候,找出来的答案是3,事实上结果应该是2..不得不吐槽数据给的还是有点弱了- =....

     

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <stack>
#include <queue>
#include <map>
#include <string>
#include <cstring>
#include <string>
using namespace std;
typedef long long ll;
const int maxn=1000000+100;
char str[maxn],s[maxn],s1[maxn];
int f[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;
    }
}
int 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 i-m+1;
    }
}


int main()
{
//    freopen("in.txt","r",stdin);
    int tt,len;
    scanf("%d",&tt);
    while(tt--)
    {
        scanf("%s\n",s);
        getFail(s,f);
        len=strlen(s);
        int pt=len;
        int ans=0;
        while(true)
        {
            if (pt>(len/3))
            {
                pt=f[pt];
                continue;
            }
            for (int i=pt+pt-1; i<=len-pt; i++)
            {
                if (f[i]==pt)
                {
                    ans=pt;
                    break;
                }
            }
            if (ans) break;
            if (pt==0) break;
            pt=f[pt];
        }
        printf("%d\n",ans);

    }
    return 0;
}

你可能感兴趣的:(hdu4763 Theme Section KMP)