- 和“阿狸的打字机”那道题很类似,也是把询问全部放到树上,拓扑排序一遍求解
点击查看代码
#include <bits/stdc++.h>
using namespace std;
string s;
int t[200005][26],tot,fail[200005],ans[200005],cnt[200005],d[200005];
vector<int>g[200005];
queue<int>q;
int read1()
{
char cc=getchar();
while(!(cc>=48&&cc<=57))
{
if(cc=='-')
{
break;
}
cc=getchar();
}
bool f=false;
int s=0;
if(cc=='-')
{
f=true;
}
else
{
s=cc-48;
}
while(1)
{
cc=getchar();
if(cc>=48&&cc<=57)
{
s=s*10+cc-48;
}
else
{
break;
}
}
if(f==true)
{
s=-s;
}
return s;
}
void insert(string s,int id)
{
int cur=0;
for(int i=0;i<s.size();i++)
{
if(t[cur][s[i]-'a']==0)
{
tot++;
t[cur][s[i]-'a']=tot;
}
cur=t[cur][s[i]-'a'];
}
g[cur].push_back(id);
}
void build()
{
for(int i=0;i<26;i++)
{
if(t[0][i]!=0)
{
q.push(t[0][i]);
}
}
while(!q.empty())
{
int n1=q.front();
q.pop();
for(int i=0;i<26;i++)
{
if(t[n1][i]!=0)
{
fail[t[n1][i]]=t[fail[n1]][i];
q.push(t[n1][i]);
}
else
{
t[n1][i]=t[fail[n1]][i];
}
}
}
for(int i=1;i<=tot;i++)
{
d[fail[i]]++;
}
}
void calc(string s)
{
int cur=0;
for(int i=0;i<s.size();i++)
{
cur=t[cur][s[i]-'a'];
cnt[cur]++;
}
for(int i=1;i<=tot;i++)
{
if(d[i]==0)
{
q.push(i);
}
}
while(!q.empty())
{
int n1=q.front();
q.pop();
d[fail[n1]]--;
cnt[fail[n1]]+=cnt[n1];
for(int i=0;i<g[n1].size();i++)
{
ans[g[n1][i]]+=cnt[n1];
}
if(d[fail[n1]]==0)
{
q.push(fail[n1]);
}
}
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
string t;
cin>>t;
insert(t,i);
}
build();
string s;
cin>>s;
calc(s);
for(int i=1;i<=n;i++)
{
printf("%d\n",ans[i]);
}
return 0;
}