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; }