AC自动机 构建完之后,由于特征码都不相同,所以沿着失配边走逐个统计即可
注意有多组输入
const int N=1e5+5;
int n,m;
int i,j,k;
char s[(int)1e3+5][55];
int tot=0,t[N][128];
int vis[N],f[N];
int ans[N];
char ch[(int)2e6+5];
void insert(char *s,int id)
{
int rt=0;
for(int i=0;s[i];i++){
int x=s[i];
if(!t[rt][x]) t[rt][x]=++tot;
rt=t[rt][x];
}
vis[rt]=id;
}
void getfail()
{
queue<int> q;
for(int i=0;i<128;i++) if(t[0][i]) f[t[0][i]]=0,q.push(t[0][i]);
while(q.size()){
int rt=q.front(); q.pop();
for(int i=0;i<128;i++){
if(t[rt][i]) f[t[rt][i]]=t[f[rt]][i],q.push(t[rt][i]);
else t[rt][i]=t[f[rt]][i];
}
}
}
void query(char *s)
{
int rt=0;
for(int i=0;s[i];i++){
int x=s[i];
rt=t[rt][x];
for(int j=rt;j;j=f[j]) if(vis[j]) ans[vis[j]]++;
}
}
void clear()
{
for(int i=0;i<=tot;i++){
ans[i]=f[i]=vis[i]=0;
for(int j=0;j<128;j++) t[i][j]=0;
}
tot=0;
}
int main()
{
//IOS;
while(~sd(n)){
for(int i=1;i<=n;i++) ss(s[i]),insert(s[i],i);
getfail();
ss(ch);
query(ch);
for(int i=1;i<=n;i++){
if(ans[i]) printf("%s: %d\n",s[i],ans[i]);
}
clear();
}
//PAUSE;
return 0;
}