hdu 4763 Theme Section(next数组找串中三段相等)

题意:在一个串中找 EAEBE 的形式的最长的E,其中E为一个字符串,也就是说找到前缀与后缀相同,并且串中还存在相同的一段,它们不能重复。

思路:利用next数组,next[len]代表的即是最大的相同的前缀与后缀,然后让 i 从len-1往前遍历找到 i>=2(前面部分最少要有2个字符),在过程中更新最长的长度ans即可。

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;

#define MaxSize 1000005

int _next[MaxSize];
char str[MaxSize];

void GetNext(char t[]){//求next数组
    int j,k,len;
    j=0;
    k=-1;
    _next[0]=-1;
    len=strlen(t);
    while(j<len){
        if(k==-1||t[j]==t[k]){
            ++j;
            ++k;
            _next[j]=k;//此句可由优化替代
            /*优化(仅保证求KMPIndex时可用。谨慎使用。)
            if(t[j]!=t[k])next[j]=k;
            else next[j]=next[k];
            */
        }
        else k=_next[k];
    }
}

int main(){
    int t,i,k,len,m,ans;
    scanf("%d",&t);
    while(t--){
        scanf("%s",str);
        GetNext(str);//求子串的next数组
        len=strlen(str);
        m=_next[len];//m代表最大的首尾相同长度
        ans=0;
        for(i=len-1;i>=2;--i){
            k=_next[i];//k为i之前与开头重复的长度
            while(k>0){
                if(k<=m&&k+k<=i&&i+k<=len){//长度小于m,且三段不重合
                    ans=max(ans,k);
                    break;//当前是最大的长度
                }
                k=_next[k];//next[k]一定小于k
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
View Code

 

posted @ 2015-08-22 15:39  gongpixin  阅读(258)  评论(0编辑  收藏  举报