这道题,很蛋疼,放了两个星期捡起来,用之前wrong answer的代码重新提交一遍竟然报TLE了!
我顿时不淡定了。
重新检查了KMP模版,搜了题解,发现一个超diao的函数 strstr ( char *a , char *b),判断b是不是a的字串,其速度竟比KMP还快,据说最新的strstr是用传说中的 TWO WAY方式写的。以后比赛还用的上kmp么,我只能说两手准备吧。
思路还是很简单,直接两个for循环利用kmp,加上一个简单的剪枝(这个剪枝。。。有点无语,感觉没什么卵用,但是不加就是会超时)
看代码。
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
char s[505][2005];
int f[2005];
void preKmp(char x[],int m,int kmpNext[])
{
int i,j;
j=kmpNext[0]=-1;
i=0;
while(i<m)
{
while(-1!=j && x[i]!=x[j])
j=kmpNext[j];
if(x[++i]==x[++j])
kmpNext[i]=kmpNext[j];
else
kmpNext[i]=j;
}
}
int find(char x[],int m, char y[],int n)
{
int i,j;
preKmp(x,m,f);
i=j=0;
while(i<n)
{
while(j!=-1 && y[i]!=x[j] )
j=f[j];
i++;j++;
if(j==m)
return 0;
}
return 1;
}
int main()
{
int T,n,i,j,m,n1,cas=0,ans,vis[505];
scanf("%d",&T);
while(T--)
{
cas++;
scanf("%d",&n);
ans=-1;
memset(vis,0,sizeof(vis));
for(i=1;i<=n;i++)
{
scanf("%s",s[i]);
for(j=1;j<i;j++)
{
if(vis[j]) continue; //如果s[j] 是j之后的某个串A的字串,则不必再检查s[j],因为不存在s[j]不是B的子串而A是B的子串的情况
m=strlen(s[j]);<span style="white-space:pre"> </span>
n1=strlen(s[i]);
if(find(s[j],m,s[i],n1))
// if(strstr(s[i],s[j])==NULL) //这个跑出来最快是327ms,KMP最快是707ms。
{
ans=i;
break;
}
else
vis[j]=1;
}
}
printf("Case #%d: %d\n",cas,ans);
}
return 0;
}