https://vjudge.net/contest/166969#problem/M
kmp一直TLE。
后来又节省他找next数组的时间(用vis数组设置)
用map记录每个串出现的字母的个数,如果子串大于母串肯定不可以。
这种剪枝都too young too naive了。
AC自动机也不能ac。。
方法。
可以想到的是,如果一个串是他前面串的子串,那么如果他前面那个串又是 他前面的前面的那个串的子串,那么他肯定也是那个串的子串(由于长度的大小关系,传递了这个关系。)
所以,我们可以忽略一些kmp的操作,进行剪枝。。
1 用find函数也是可以的,不过要同步输出流。
2 其实不用kmp用strttr也是可以的,可以说是嘎嘎好使
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <cstring>
using namespace std;
char a[550][2010];
int nex[2010];
void getNex(char t[])
{
int len =strlen(t);
memset(nex,-1,sizeof(nex));
int i = 0,k=-1;
while(i<len)
{
if(k==-1 || t[i]==t[k])
{
i++,k++;
nex[i] = k;
}
else
k = nex[k];
}
}
int kmp(char s1[],char s2[])
{
int len1 = strlen(s1),len2 =strlen(s2);
int i=0,j=0,cnt=0;
getNex(s2);
while(i<len1 && j<len2)
{
if(s1[i]==s2[j])
{
i++;
j++;
if(j==len2)
{
cnt++;
return 1;
//j = 0;
}
}
else if(j==0)
i++;
else
j = nex[j];
}
return 0;
}
int main()
{ //ios::sync_with_stdio(false);
int m,n;
int t;
bool vis[555];
scanf("%d",&t);
for(int tt=1;tt<=t;tt++)
{ scanf("%d",&m);
for(int i=1;i<=m;i++)
scanf("%s",a[i]);
int k=-1;
memset(vis,false,sizeof(vis));
int flag=-1;
for(int i=1;i<=m;i++)
{
for(int j=i-1;j>=1;j--)
{ if(vis[j]) continue;
if(kmp(a[i],a[j])==0)
{ flag=i;
}
else
vis[j]=true;
}
}
printf("Case #%d: %d\n",tt,flag);
}
return 0;
}
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <cstring>
#include <map>
using namespace std;
string a[550];
int nex[550][2010];
int main()
{ ios::sync_with_stdio(false);
int m,n;
int t;
//map<char,int>mp[550];
cin>>t;
for(int tt=1;tt<=t;tt++)
{ //memset(vis,false,sizeof(vis));
cin>>m;
for(int i=1;i<=m;i++)
{cin>>a[i];
}
int ans=-1;
bool vis[555];
memset(vis,false,sizeof(vis));
for(int i=1;i<=m;i++)
{
for(int j=i-1;j>=1;j--)
{ if(vis[j]) continue;
if(a[i].find(a[j])==string::npos)
ans=i;
else vis[j]=true;
}
}
//printf("Case #%d: %d\n",tt,ans);
//for(int i=1;i<=m;i++)
//if(vis[i])
//cout<<"@@@@@@@@@@@@@@"<<endl;
cout<<"Case #"<<tt<<": "<<ans<<endl;
}
return 0;
}