zoukankan      html  css  js  c++  java
  • HDU 4763 Theme Section ( KMP )

    题意 : 现有一字符串S,要求在S中找到最长的子串E,使得S满足格式“EAEBE”,其中A,B可以为任意的S子串。也就是说子串E既是S的前缀也是S的后缀,同时还在S中间出现,但不与前缀E与后缀E重叠。

    分析 :  使用KMP的Next数组的特点,我们能够找出字符串所有相同的前后缀,即递推 Next[ Next[ Next[ ... ] ] ] ,找到之后便只要截取字符串再去跑一遍KMP看看中间串是否包含这个前后缀即可

    #include<string.h>
    #include<stdio.h>
    using namespace std;
    const int maxn = 1e6 + 10;
    char Origin[maxn], mo[maxn], str[maxn];
    int O_Next[maxn], OriginL, moNext[maxn], moL, strL;
    inline void GetNext(char * MO, int * Next)
    {
        int len = strlen(MO);
        int i = 0, j = -1;
        Next[i] = j;
        while(i < len){
            while(j!=-1 && MO[i]!=MO[j]) j = Next[j];
            Next[++i] = ++j;
        }
    }
    bool Match()
    {
        int i = 0, j = 0;
        while(i < strL && j < moL){
            while(j!=-1 && mo[j]!=str[i]) j = moNext[j];
            i++, j++;
        }
        if(j == moL) return true;
        else return false;
    }
    inline void PrintAns()
    {
        GetNext(Origin, O_Next);
        for(int i=OriginL; i!=-1&&i!=0; i=O_Next[i]){
            if(OriginL - 2*i - 2 < i) continue;
            else{
                strncpy(mo, Origin, i);
                mo[i] = '';
                //puts(mo);
                GetNext(mo, moNext);
                strncpy(str, Origin+i+1, OriginL-2*i-2);
                str[OriginL-2*i-2] = '';
                //puts(str);
                if(Match()){
                    printf("%d
    ", i);
                    return ;
                }
            }
        }
        puts("0");
    }
    int main(void)
    {
        int nCase;
        scanf("%d", &nCase);
        while(nCase--){
            scanf("%s", Origin);
            OriginL = strlen(Origin);
            if(OriginL < 3) puts("0");
            else{
                if(OriginL == 3){
                    if(Origin[0]==Origin[1] && Origin[1]==Origin[2]) puts("1");
                    else puts("0");
                }else PrintAns();
            }
        }
        return 0;
    }
    View Code

    截取可以使用 strncpy( 结果串, 原串+n, len ) 即能将原串从第 n 个开始的字符截取长度为 len 的子串。

  • 相关阅读:
    (最大团) poj 3692
    (floyd+匈牙利算法) poj 3216
    (floyd+匈牙利算法) poj 2594
    (最小点覆盖) hdu 1054
    (最小点覆盖) hdu 4619
    (最小点覆盖) hdu 1498
    (匈牙利算法+贪心) hdu 3729
    (匈牙利算法) hdu 5093
    (匈牙利算法) bzoj 1059
    (二分+匈牙利算法) hdu 2236
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/7598812.html
Copyright © 2011-2022 走看看