题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5510
对于字符串si和si+1,如果si是si+1的子串,那么在判断si+1和si+2的时候,只需要判断si+1是不是si+2的子串即可,si可忽略掉。
但是如果si不是si+1的子串,那么在判断si+1和si+2的时候,需要判断si是不是si+2的子串
这种关系用一个visit数字保存,暴力kmp即可
#include<bits/stdc++.h>
using namespace std;
char s[510][2010];
bool vis[510];
int _next[510][10010];
int p,q;
void getnext(char a[2010],int x)
{
int j, k;
j=0;
k=-1;
_next[x][0]=-1;
int m=strlen(a);
while(j<m)
if(k == -1 || a[j] == a[k])
_next[x][++j] = ++k;
else
k = _next[x][k];
}
bool pin(char a[2010],char b[2010],int x)
{
p=strlen(a);
q=strlen(b);
int j=0;
for(int i=0;i<q;i++)
{
if(b[i]==a[j])
{
j++;
if(j==p)
return true;
}
else if(_next[x][j]!=-1)
j=_next[x][j],i--;
else
j=0;
}
return false;
}
int main()
{
int t;
scanf("%d",&t);
int cas=1;
while(t--)
{
int n;
scanf("%d",&n);
int id=-1;
int now=1;
// ac.build();
scanf("%s",s[1]);
getnext(s[1],1);
memset(vis,0,sizeof vis);
// for(int i=0;i<strlen(a);i++)
// printf("next %d=%d\n",i,_next[i]);
for(int i=2;i<=n;i++)
{
scanf("%s",s[i]);
getnext(s[i],i);
for(int j=i-1;j>0;j--)
{
if(vis[j])
continue;
if(!pin(s[j],s[i],j))
{
id=i;
break;
}
else
vis[j]=1;
}
// printf("a=%s\n",a);
// for(int i=0;i<strlen(a);i++)
// printf("next %d=%d\n",i,_next[i]);
}
printf("Case #%d: %d\n",cas++,id);
}
return 0;
}