这道题,很蛋疼,放了两个星期捡起来,用之前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; }