首页 > 代码库 > hdu4763(KMP的应用)

hdu4763(KMP的应用)

题意:给一个字符串,问最长的一个子串A,他是前缀,同时是后缀,并且中间也出现过A。并且出现的三个A都不没有重叠部分。


解法:先KMP求出失配数组,然后将所有的是后缀且是前缀的打上标记,然后遍历整个next数组,(对于每个位置的next来说,一直next向前取就是找到此前缀的一个个是整个字符串前缀的后缀,比较绕)暴力枚举判断每个串的所有匹配前缀的后缀是否合法。


代码:

/****************************************************
* author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>

using namespace std;

#define eps 1e-8
typedef long long LL;

int next1[1001000];
void getNext(char *s)
{
    int len=strlen(s);
    int i=0;
    int j=next1[0]=-1;
    while(i<len)
    {
        while(j!=-1&&s[i]!=s[j]) j=next1[j];
        next1[++i]=++j;
    }
}

char s[1000100];
bool rem[1000100];

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        memset(rem,0,sizeof rem);
        scanf("%s",s);
        getNext(s);
        int len=strlen(s);
        int tool=next1[len];
        while(tool)
        {
            rem[tool]=1;
            tool=next1[tool];
        }
        int out=0;
        for(int i=len-1; i>1; i--)
        {
            int t=i;
            while(t!=-1)
            {
                if(rem[next1[t]]&&len-next1[t]>=i&&i-next1[t]>=next1[t])
                {
                    out=max(out,next1[t]);
                    break;
                }
                t=next1[t];
            }
        }
        cout<<out<<‘\n‘;
    }
    return 0;
}