HDU 4763 Theme Section(KMP:后缀与前缀)

HDU 4763 Theme Section(KMP:后缀与前缀)

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

题意:给你一个字符串T,要你在中间找一段连续的串,使得该串与T的前缀相同,并且和T的后缀相同.(但是不重叠)

分析:

       首先我们要知道KMP算法可以用来求T串的next[i],next[i]=x表示以第i-1字符结尾的后缀 与T串前缀的最大匹配长度为x.

       目标串的长度为len,则len<=m  (m==strlen(T)/3).且len=min(len,next[m]),然后我们从第1号(0号开始计数)字符开始循环到第n-2号字符,利用当前字符的next值可以知道以当前字符的前一个字符为结尾的后缀最多能匹配T的前缀长度,在这个扫描过程中,我们求出合法(即不重叠的)的最大要求段长,且这个段长肯定<=len.

AC代码:

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
char T[1000000+1000];
int next[1000000+1000];
int n,m;
void getFail()
{
    next[0]=next[1]=0;
    for(int i=1;i<m;i++)
    {
        int j=next[i];
        while(j && T[i]!=T[j]) j=next[j];
        next[i+1]= (T[i]==T[j])?j+1:0;
    }
}
int main()
{
    while(scanf("%d",&n)==1)
    {
        while(n--)
        {
            scanf("%s",T);
            m=strlen(T);
            getFail();
            int len = min(m/3 , next[m]);
            if(len==0)
            {
                printf("0\n");
                continue;
            }
            int max_len=0;
            for(int i=2;i<m;i++)
            {
                if(next[i]>len)continue;
                else if(next[i]>max_len)//可能可行
                {
                    int len1=min(i/2 , next[i]);//求出i-1的后缀与T的前缀的最大不重叠公共部分
                    if(len1>max_len && m-len1>=i)//判断T的长len1的后缀是不是已经延伸到了i-1位置,如果是,那么就重叠了
                        max_len=len1;
                }
            }
            printf("%d\n",max_len);
        }
    }
    return 0;
}


你可能感兴趣的:(ACM)