#include<iostream>
#include<cstdio>
#include<string.h>
#include<string>
#include<set>
#include<algorithm>
#include<cmath>
#include<queue>
#define ll __int64
#define MAX 2000009
using namespace std;
const int maxnode = MAX;
const int sigma_size = 128;
char ss[5009][1009];
int next[maxnode][sigma_size];
int end[maxnode];
int fail[maxnode];
int num[maxnode];
struct Tire
{
int sz;
int root;
int newnode()
{
for(int i = 0; i<sigma_size; i++)
next[sz][i] = -1;
end[sz++] = -1;
return sz - 1;
}
void init()
{
sz = 0;
root = newnode();
}
void insert(char* s,int id)
{
int len =strlen(s);
int u = root;
for(int i = 0; i<len; i++)
{
if(next[u][s[i]]==-1)
next[u][s[i]] = newnode();
u = next[u][s[i]];
}
end[u] = id;
}
void build()
{
queue<int>Q;
fail[root] = root;
for(int i = 0; i<sigma_size; i++)
{
if(next[root][i]==-1)
next[root][i] = root;
else
{
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
}
while(!Q.empty())
{
int now = Q.front();
Q.pop();
for(int i = 0;i<sigma_size;i++)
{
if(next[now][i]==-1)
next[now][i] = next[fail[now]][i];
else
{
fail[next[now][i]] = next[fail[now]][i];
Q.push(next[now][i]);
}
}
}
}
void query(char* s,int n)
{
for(int i = 0;i<n;i++)
num[i] = 0;
int len = strlen(s);
int now = root;
for(int i = 0;i<len;i++)
{
now = next[now][s[i]];
int temp = now;
while(temp!=root)
{
if(end[temp]!=-1)
{
// cout<<end[temp]<<endl;
num[end[temp]]++;
}
temp = fail[temp];
}
}
for(int i =0;i<n;i++)
{
if(num[i]>0)
{
printf("%s: %d\n",ss[i],num[i]);
}
}
}
}AC;
char buf[maxnode];
int main()
{
int t;
while(~scanf("%d",&t))
{
AC.init();
for(int i = 0;i<t;i++)
{
scanf("%s",ss[i]);
AC.insert(ss[i],i);
}
AC.build();
scanf("%s",buf);
AC.query(buf,t);
}
return 0;
}
AC自动机的基础题,按照模板打的,还是不熟悉啊,每次找bug的时候,都感觉真是够了