您的位置:首页 > 其它

[BZOJ2754] 喵星球上的点名 - AC自动机/后缀数组/后缀自动机/玄学♂暴力

2016-07-29 12:55 288 查看
纸张蒟蒻zzt只会写sam只会套板子qaq

#include"bits/stdc++.h"
using namespace std;

#define mmap(x,y) make_pair(x,y)
#define fge getchar()
template <class MyInt>
inline void read(MyInt&x){
x=0;int f=1;char ch=fge;
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=fge;}
while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=fge;
x=x*f;
}

const int N=20005,M=50005,L=100005;
struct node{
map<int,node*> go;
set<int> res;
node * fail;
int len;
node ();
} *null= new node(), e[2*L+4*N];
node::node (){
fail=null;
len=0;
};

set<int>un;

struct SAM{
int str[L+2*N],l,tot,n,m,match
,tmp,res
;
node *last;
#define E map<int,node*>::iterator
SAM(){last=&e[1];tmp=1;}
void extend(int c,int value){
node*p=last,*np=&e[++tmp];last=np;
np->len=p->len+1;np->res.insert(value);
while(p->go.find(c)==p->go.end()&&p!=null)
p->go.insert(mmap(c,np)),p=p->fail;
if(p==null) np->fail=e+1;
else {
node*q=p->go.find(c)->second,*nq;
if(q->len==p->len+1)np->fail=q;
else {
nq=&e[++tmp];
for(E i=q->go.begin();i!=q->go.end();i++)
nq->go.insert(*i);
nq->len=p->len+1;nq->fail=q->fail;
np->fail=q->fail=nq;node*i;E j;
for(i=p;(j=i->go.find(c))!=i->go.end()&&j->second==q;i=i->fail)
j->second=nq;
}
}
}
int s[2*L+4*N],q[2*L+4*N];
void pre(){
read(n),read(m);int i,p,j;
for(i=1;i<=n;i++){
for(j=l+1,read(p);j<=l+p;j++)
read(str[j]),extend(str[j],i);
l+=p+1;str[l]=10001;extend(str[l],0);
for(j=l+1,read(p);j<=l+p;j++)
read(str[j]),extend(str[j],i);
l+=p+1;str[l]=10001;extend(str[l],0);
}
for(i=1;i<=tmp;i++)s[e[i].len]++;
for(i=1;i<=tmp;i++)s[i]+=s[i-1];
for(i=tmp;i;i--)q[s[e[i].len]--]=i;
for(i=tmp;i;i--){
set<int>::iterator j;
if(e[q[i]].res.empty()) continue;
for(j=e[q[i]].res.begin();j!=e[q[i]].res.end();j++)
e[q[i]].fail->res.insert(*j);
}
e[1].res.clear();
null->res.clear();
}
void work(){
int i,p,j,ans;
for(i=1;i<=m;i++){
node*now=e+1;
for(j=1,read(p);j<=p;j++){
read(match[j]);
E w=now->go.find(match[j]);
if(w==now->go.end())now=null;
else now=w->second;
}
ans=now->res.size();
set<int>::iterator k;
for(k=now->res.begin();k!=now->res.end();k++)
res[*k]++;
printf("%d\n",ans);
}
for(i=1;i<n;i++)
printf("%d ",res[i]);
printf("%d",res
);
}
} sam;

int main(){
sam.pre();sam.work();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: