题意:有 n n n个长度为 m m m的串,求在长度为 L L L 的串中这 n n n个串中任意一个串出现的最早位置,如果 n n n个串都没有,输出 n o no no。 ( m ≤ 20 , n ≤ 1 e 4 , L ≤ 1 e 5 ) (m≤20,n≤1e4,L≤1e5) (m≤20,n≤1e4,L≤1e5)
做法,因为每一个串长度都是一样的,考虑在最后的串内枚举每一段长度为 m m m的串,看它是否为 n n n个串中的一个。这里使用双哈希,首先先将 n n n串的哈希值算出,作为一个 p a i r pair pair类型放入 m a p map map中,然后算出最后一个串的哈希前缀和,枚举比较输出即可。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<map>
#define ull unsigned long long
using namespace std;
const ull c1=19260817;
const ull c2=1e9+7;
map<pair<ull,ull>,int> mp;
int l,n,m;
char s[1001000],t[1001000];
ull mi1[1001000],mi2[1001000],h1[1001000],h2[1001000];
pair<ull,ull> gethash(int l,int r)
{
ull x=h1[r]-h1[l-1]*mi1[r-l+1];
ull y=h2[r]-h2[l-1]*mi2[r-l+1];
return make_pair(x,y);
}
int main()
{
bool flag=0;
mi1[0]=mi2[0]=1;
cin>>l>>n>>m;
for(int i=1;i<=l;++i)
{
mi1[i]=mi1[i-1]*c1;
mi2[i]=mi2[i-1]*c2;
}
for(int i=1;i<=n;++i)
{
ull h1=0,h2=0;
scanf("%s",s+1);
for(int j=1;j<=m;++j)
{
h1=h1*c1+s[j]-'a'+1;
h2=h2*c2+s[j]-'a'+1;
}
mp[make_pair(h1,h2)]=1;
}
scanf("%s",t+1);
for(int i=1;i<=l;++i)
{
h1[i]=h1[i-1]*c1+t[i]-'a'+1;
h2[i]=h2[i-1]*c2+t[i]-'a'+1;
}
for(int i=1;i<=l;++i)
{
int j=i+m-1;
if(j>l)
break;
if(mp[gethash(i,j)])
{
flag=1;
printf("%d",i);
break;
}
}
if(!flag)
cout<<"no";
return 0;
}