【BZOJ2754】喵星球上的点名(AC自动机)
【BZOJ2754】喵星球上的点名(AC自动机)
题面
题解
友情提示:此题请不要在cogs上提交,它的数据有毒
对于点名串构建\(AC\)自动机
然后把名字丢进去进行匹配,
大力统计一下答案即可
当然,要用\(map\)记录\(trie\)树
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 52000
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
void ReadStr(vector<int> &a)
{
int x=read();
a.resize(x+1);
a[0]=x;
for(int i=1;i<=x;++i)a[i]=read();
}
vector<int> nam[MAX],fam[MAX];
vector<int> sub[MAX];
map<int,int>::iterator it;
int n,m;
struct Node
{
map<int,int> son;
int ff,fl;
set<int> lst;
}t[MAX<<2];
int tot,vis[MAX],ans1[MAX],ans2[MAX];
void insert(vector<int> a,int g)
{
int now=0;
for(int i=1;i<=a[0];++i)
{
if(!t[now].son[a[i]])
t[now].son[a[i]]=++tot;
now=t[now].son[a[i]];
}
t[now].lst.insert(g);
t[now].fl=1;
}
void BuildFail()
{
queue<int> Q;
for(it=t[0].son.begin();it!=t[0].son.end();++it)Q.push(it->second);
while(!Q.empty())
{
int u=Q.front();Q.pop();
if(!t[u].son.size())continue;
for(it=t[u].son.begin();it!=t[u].son.end();++it)
{
int v=it->second,c=it->first,p=t[u].ff;
while(p&&!t[p].son[c])p=t[p].ff;
if(t[p].son[c])t[v].ff=t[p].son[c];
Q.push(v);
t[v].fl|=t[t[v].ff].fl;
}
}
}
void Work(vector<int> a,int str)
{
int now=0;
for(int i=1;i<=a[0];++i)
{
int c=a[i];
if(t[now].son[c])now=t[now].son[c];
else
{
while(now&&!t[now].son[c])now=t[now].ff;
if(t[now].son[c])now=t[now].son[c];
}
if(t[now].fl)
{
int p=now;
while(p)
{
for(set<int>::iterator it=t[p].lst.begin();it!=t[p].lst.end();++it)
if(vis[*it]!=str){ans1[*it]++;ans2[str]++;vis[*it]=str;}
p=t[p].ff;
}
}
}
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;++i)
{
ReadStr(nam[i]);
ReadStr(fam[i]);
}
for(int i=1;i<=m;++i)ReadStr(sub[i]);
for(int i=1;i<=m;++i)insert(sub[i],i);
BuildFail();
for(int str=1;str<=n;++str)
{
Work(nam[str],str);
Work(fam[str],str);
}
for(int i=1;i<=m;++i)printf("%d\n",ans1[i]);
for(int i=1;i<=n;++i){printf("%d",ans2[i]);(i==n)?putchar('\n'):putchar(' ');}
return 0;
}