由于是英文题,简要解释一下题目。
开始给出n个子串,和m个询问,对于每个询问读入一个子串,询问n个子串中,有多少个子串包含所询问的子串。
实在看不懂的可以从样例中意会一下。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <set>
using namespace std;
const int maxn =505000;
int n,m,cnt,tot,len,ans[maxn];
char s[maxn];
vector<int> f[maxn];
set<int> T[maxn];
set<int> :: iterator it;
struct sam
{
int last,dfn;
int seq[maxn],a[maxn][27],mx[maxn],fa[maxn],sum[maxn];
sam(){
last=cnt++;
}
void insert(int c,int id)
{
int p=last,np=last=++cnt;mx[np]=mx[p]+1;T[np].insert(id);
while(!a[p][c]&&p) a[p][c]=np,p=fa[p];
if(!p) fa[np]=1;
else
{
int q=a[p][c];
if(mx[p]+1==mx[q]) fa[np]=q;
else
{
int nq=++cnt;mx[nq]=mx[p]+1;
memcpy(a[nq],a[q],sizeof(a[q]));
fa[nq]=fa[q];
fa[np]=fa[q]=nq;
while(a[p][c]==q) a[p][c]=nq,p=fa[p];
}
}
}
void dfs(int u)
{
for(int i=0;i<f[u].size();i++){
int v=f[u][i];
dfs(v);
if(T[u].size()<T[v].size()) swap(T[u],T[v]);
for(it=T[v].begin();it!=T[v].end();it++)
T[u].insert(*it);
}
sum[u]=T[u].size();
}
void work()
{
for(int i=1;i<=n;i++){
scanf("%s",s);
last=1;len=strlen(s);
for(int j=0;j<len;j++) insert(s[j]-'a',i);
}
for(int i=1;i<=cnt;i++) f[fa[i]].push_back(i);
dfs(1);
for(int i=1;i<=m;i++){
bool flag=true;
scanf("%s",s);int l=strlen(s),p=1;
for(int j=0;j<l;j++){
int c=s[j]-'a';
if(!a[p][c]) {flag=false;break;}
p=a[p][c];
}
if(flag) printf("%d\n",sum[p]);
else puts("0");
}
}
}sam;
int main()
{
scanf("%d%d",&n,&m);
sam.work();
return 0;
}
/*
3 3
abcabcabc
aaa
aafe
abc
a
ca
*/