HDU 4763 Theme Section (KMP)

来源:互联网 发布:vb冒泡排序法代码 编辑:程序博客网 时间:2024/05/27 19:25

先KMP求出f数组。


然后令j等于f[len],在j沿着失配边走到0的路径上(即一直j=f[j]),每个节点都代表了一对相同的前后缀,且长度为f[j]。

这些对前后缀都可能是答案子串,再用kmp算法在中间找这个子串存不存在即可。

注意,子串长度会越来越小,而且一定包含于之前判断过的子串中(因为起点一样)。所以若前一个子串在l到r区间不存在,那么下一个子串也一定不存在。这样记录已扫描区间的范围,只去看这个范围外的即可。保证每个位置只被查过一次,复杂度O(N)。


代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;char s[1000005];int f[1000005];void getfail(){    f[0]=f[1]=0;    int len=strlen(s);    for(int i=1;i<len;i++){        int j=f[i];        while(j&&s[i]!=s[j]) j=f[j];        f[i+1]=(s[i]==s[j]? j+1:0);    }}int main(){    int T;    scanf("%d",&T);    while(T--){        scanf("%s",&s);        int len=strlen(s);        getfail();        int l=f[len];        int r=len-l;        while(l>r){            l=f[l];            r=len-r;        }        int sl=r,sr=l;        bool ok=0;        int res=0;        while(1){            int j=0;            for(int i=l;i<sl;i++){                while(j&&s[j]!=s[i]) j=f[j];                if(s[j]==s[i]) j++;                if(j==l){                    ok=1;                    break;                }            }            j=0;            for(int i=sr;i<r;i++){                while(j&&s[j]!=s[i]) j=f[j];                if(s[j]==s[i]) j++;                if(j==l){                    ok=1;                    break;                }            }            if(ok){                res=l;                break;            }            sl=l;            sr=r;            l=f[l];            r=len-l;            if(!l){                res=0; break;            }        }        printf("%d\n",res);    }    return 0;}


0 0
原创粉丝点击