Theme Section HDU - 4763

http://acm.hdu.edu.cn/showproblem.php?pid=4763

数据水 当初n^2都能过

将所给串所有公共前缀后缀长度都找出来 然后二分长度 看中间剩下的那部分是否包含二分的这个公共前缀后缀

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;

int nxtt[maxn],nxts[maxn],len[maxn];
char ch[maxn],s[maxn],t[maxn];
int n,tot;

void kmp(char *t,int lt)
{
    int i,j;
    nxtt[0]=-1;
    i=0,j=-1;
    while(i<lt)
    {
        if(j==-1||t[i]==t[j])
        {
            i++,j++;
            nxtt[i]=j;
        }
        else j=nxtt[j];
    }
}

bool solveII(char *s,int ls,char *t,int lt)
{
    int i,j;
    i=0,j=0;
    while(i<ls)
    {
        if(j==-1||s[i]==t[j])
        {
            i++,j++;
            nxts[i]=j;
            if(j==lt) return 1;
        }
        else j=nxtt[j];
    }
    return 0;
}

bool solveI(int p)
{
    int i;
    if(3*p>n) return 0;
    for(i=0;i<p;i++) t[i]=ch[i];
    for(i=p;i<n-p;i++) s[i-p]=ch[i];
    kmp(t,p);
    return solveII(s,n-2*p,t,p);
}

int main()
{
    int t,i,l,r,m,ans;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%s",ch);
        n=strlen(ch);
        kmp(ch,n);
        i=nxtt[n],tot=0;
        while(i!=0)
        {
            len[++tot]=i;
            i=nxtt[i];
        }
        l=1,r=tot;
        while(l<r) swap(len[l++],len[r--]);

        l=1,r=tot,ans=0;
        while(l<=r)
        {
            m=(l+r)/2;
            if(solveI(len[m])) l=m+1,ans=len[m];
            else r=m-1;
        }
        printf("%d\n",ans);
    }
    return 0;
}

/*
1
aaaaaaaaaa
*/

猜你喜欢

转载自blog.csdn.net/sunyutian1998/article/details/82967234