分析:从后往前扫,维护
r
(当前串是第
复杂度: o(nl)
代码:
#include <bits/stdc++.h>
#define LL long long
#define FOR(i,x,y) for(int i = x;i < y;++ i)
#define IFOR(i,x,y) for(int i = x;i > y;-- i)
#define MAXN 20010
using namespace std;
/**
nt[i]的代表以0...i的最长公共前缀后缀
即:0...nt[i] == i-nt[i]...i
**/
int nt[MAXN];
/**nt[]数组的取得
如果没有符合的公共前后缀 nt[i]=-1;
如果nt[i]=k; s[i+1] = s[k+1] nt[i] = k+1;
**/
void Get_Next(char* s){
nt[0] = -1;
int k = nt[0];
int len_s = strlen(s);
for(int i = 0;i < len_s-1;i ++){
while(s[i+1] != s[k+1] && k != -1) k = nt[k];
if(k != -1) k++;
else if(k == -1 && s[i+1] == s[k+1]) k++;
nt[i+1] = k;
}
}
/**
p为模式串
**/
bool KMP_Match(char* s,char* p){
int k = -1;///这里应该是-1,上次写好像搞错了
int len_s = strlen(s),len_p = strlen(p);
for(int i = 0;i < len_s;i ++){
while(s[i] != p[k+1] && k != -1) k = nt[k];
if(k != -1) k++;
else if(k == -1 && s[i] == p[k+1]) k++;
if(k == len_p-1) return true;
}
return false;
}
int n;
char s[502][MAXN];
int main()
{
//freopen("test.in","r",stdin);
int T,tCase = 0; scanf("%d",&T);
while(T--){
printf("Case #%d: ",++tCase);
scanf("%d",&n);
FOR(i,0,n) scanf("%s",s[i]);
int l = -1,r = -1;
IFOR(i,n-2,-1){
Get_Next(s[i]);
if(!KMP_Match(s[i+1],s[i])){
l = i;
FOR(j,i+2,n){
if(KMP_Match(s[j],s[i])){
r = j;
break;
}
}
if(r == -1){
r = n;
}
break;
}
}
if(l == -1){
printf("-1\n");
continue;
}
if(r == n){
printf("%d\n",n);
continue;
}
IFOR(i,l-1,-1){
Get_Next(s[i]);
while(r < n && !KMP_Match(s[r],s[i])){
r ++;
}
if(r == n) break;
}
printf("%d\n",r);
}
return 0;
}