标签:bzoj2780 spoj8093 sevenk love oimaster 后缀自动机 树状数组
#include <stdio.h> int main() { puts("转载请注明出处谢谢"); puts("http://blog.csdn.net/vmurder/article/details/43015849"); }
题意:
n,m
n个串
m个串
样例里面倒数第二行的you应该扔到下一行。
问m个串每个在前n个串中的几个出现过。
题解:
首先这道题跟
是一样的,只不过更卡时一点,或者说喵的数据太弱。
这道题虽然是后缀自动机,但是大体思路和
【BZOJ2434】【NOI2011】阿狸的打字机
AC自动机
是一样的。都是dfs序+树状数组优化
好了,说这道题。
就是我们建广义后缀树【就是多串的反序后缀自动机】
然后根据dfs序快速转移,用树状数组维护某区间有多少个不同的串。
我来贴两个详细的 题解
网址
16bitwar:http://blog.csdn.net/jiangyuze831/article/details/42964105
wyfcyx:http://wyfcyx.is-programmer.com/posts/76391.html
代码:
#include <map> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 201000 #define T 26 using namespace std; struct Suffix_Tree // 广义后缀树 { int head[N],next[N],v[N],cnt; void add(int u,int _v) { v[++cnt]=_v; next[cnt]=head[u]; head[u]=cnt; } int in[N],out[N],dfn,stk[N]; void build_dfn(int x) { in[x]=++dfn; stk[dfn]=x; for(int i=head[x];i;i=next[i]) build_dfn(v[i]); out[x]=dfn; } }sft,belong; struct QUERY { int id,p; QUERY(int _id=0,int _p=0):id(_id),p(_p){} bool operator < (const QUERY &a)const {return sft.out[p]<sft.out[a.p];} }ask[N]; int vis[N],ans[N]; char s[N]; int n,m; struct FENWICK { int a[N],cnt[N]; void add(int p,int x){for(;p<N;p+=p&-p)a[p]+=x;} int query(int p) { int ans=0,temp=p; for(p=sft.out[temp] ;p;p-=p&-p)ans+=a[p]; for(p=sft.in[temp]-1;p;p-=p&-p)ans-=a[p]; return ans; } }fw; struct SAM // 广义后缀自动机 { map<int,int>next[N]; int pa[N],deep[N]; int root,last,cnt; int newnode(int dep){deep[++cnt]=dep;return cnt;} void init(){root=last=cnt=1;} void add(char alp,int id) // 建立广义后缀自动机 { int np=next[last][alp]; if(np) { if(deep[np]==deep[last]+1)last=np; else { int nq=newnode(deep[last]+1); pa[nq]=pa[np],pa[np]=nq; next[nq]=next[np]; int p=last; while(p&&next[p][alp]==np) next[p][alp]=nq,p=pa[p]; last=nq; } } else { np=newnode(deep[last]+1); int p=last; while(p&&!next[p][alp])next[p][alp]=np,p=pa[p]; if(!p)pa[np]=root; else { int q=next[p][alp]; if(deep[q]==deep[p]+1)pa[np]=q; else { int nq=newnode(deep[p]+1); pa[nq]=pa[q],pa[q]=pa[np]=nq; next[nq]=next[q]; while(p&&next[p][alp]==q) next[p][alp]=nq,p=pa[p]; } } last=np; } belong.add(last,id); } void build_sft(){for(int i=2;i<=cnt;i++)sft.add(pa[i],i);} void deal_query() { bool find; int i,j,p; for(int i=1;i<=m;i++) { scanf("%s",s),find=1; for(p=root,j=0;s[j];j++) { if(!next[p][s[j]]){find=0;break;} p=next[p][s[j]]; } if(find)ask[i]=QUERY(i,p); else ask[i]=QUERY(i,-1); } sort(ask+1,ask+m+1); } }sam; int main() { // freopen("test.in","r",stdin); int i,j,k; scanf("%d%d",&n,&m); sam.init(); for(i=1;i<=n;i++) { scanf("%s",s); sam.last=sam.root; for(j=0;s[j];j++)sam.add(s[j],i); } sam.build_sft(); sft.build_dfn(1); sam.deal_query(); for(k=1;k<=m&&ask[k].p==-1;k++); for(j=1;j<=sam.cnt;j++) { int u=sft.stk[j]; for(i=belong.head[u];i;i=belong.next[i]) { int v=belong.v[i]; fw.add(j,1); if(vis[v])fw.add(vis[v],-1); vis[v]=j; } while(sft.out[ask[k].p]==j) { ans[ask[k].id]=fw.query(ask[k].p); k++; } } for(i=1;i<=m;i++)printf("%d\n",ans[i]); return 0; }
【BZOJ2780】【Spoj8093】 Sevenk Love Oimaster 后缀自动机
标签:bzoj2780 spoj8093 sevenk love oimaster 后缀自动机 树状数组
原文地址:http://blog.csdn.net/vmurder/article/details/43015849