题目:
吐槽:
题目要求多组数据;ljHDU居然有叫next的东西和我的next冲突。
题解:
建立fail树,让字符串在树上自由的奔跑然后统计子树和
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
char vir[50005][55],st[2000005];
int ch[50005][130],tot,fail[50005],size[50005],cnt[50005],point[50005],nxt[50005],v[50005],tt;
int is_end[50005];
void addline(int x,int y)
{
tt++; nxt[tt]=point[x]; point[x]=tt; v[tt]=y;
}
void trie(int id)
{
int l=strlen(vir[id]),now=0,i;
for (int i=0;i<l;i++)
{
int x=vir[id][i];
if (!ch[now][x]) ch[now][x]=++tot;
now=ch[now][x];
}
is_end[id]=now;
}
void sp()
{
int i;
queue<int>q;
for (i=0;i<=128;i++)
if (ch[0][i]) q.push(ch[0][i]);
while (!q.empty())
{
int now=q.front();q.pop();
for (i=0;i<=128;i++)
{
if (!ch[now][i])
{
ch[now][i]=ch[fail[now]][i];
continue;
}
fail[ch[now][i]]=ch[fail[now]][i];
q.push(ch[now][i]);
}
}
}
void dfs(int now)
{
size[now]=cnt[now];
for (int i=point[now];i;i=nxt[i])
{
dfs(v[i]);
size[now]+=size[v[i]];
}
}
void ac()
{
scanf("%s",st);
int l=strlen(st),now=0,i;
for (i=0;i<l;i++)
{
int x=st[i];
cnt[ch[now][x]]++;
now=ch[now][x];
}
}
int main()
{
int n,i,T;
while (~scanf("%d",&n))
{
if (n==0) break;
tt=0;
tot=0;
memset(cnt,0,sizeof(cnt));
memset(size,0,sizeof(size));
memset(is_end,0,sizeof(is_end));
memset(point,0,sizeof(point));
memset(nxt,0,sizeof(nxt));
memset(ch,0,sizeof(ch));
memset(fail,0,sizeof(fail));
for (i=1;i<=n;i++)
{
scanf("%s",vir[i]);
trie(i);
}
sp();
ac();
for (i=1;i<=tot;i++) addline(fail[i],i);
dfs(0);
int l=strlen(st);
for (i=1;i<=n;i++)
if (size[is_end[i]])
printf("%s: %d\n",vir[i],size[is_end[i]]);
}
}