luogu SP8093 后缀自动机+树状数组+dfs序
Posted guangheli
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu SP8093 后缀自动机+树状数组+dfs序相关的知识,希望对你有一定的参考价值。
这题解法很多,简单说几个:
1. 线段树合并,时间复杂度是 $O(nlog^2n)$ 的.
2. 暴力跳 $fail,$ 时间复杂度 $O(n\sqrt n),$ 比较暴力.
3. 建立后缀树后在 $dfs$ 序上数点,时间复杂度为 $O(nlogn),$ 十分优秀.
Code:
#include <bits/stdc++.h> #define N 200007 #define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout) using namespace std; struct ques int l,r,id; ques(int l=0,int r=0,int id=0):l(l),r(r),id(id) q[N]; struct P int len,f,ch[27]; vector<int>v; t[N<<1]; char S[N]; vector<int>G[N]; int tot,last,edges,tim,cnt; int hd[N],to[N],nex[N],st[N],ed[N],size[N],dfn[N],lst[N],C[N],answer[N]; int lowbit(int t) return t&(-t); void update(int x,int delta) for(;x<N;x+=lowbit(x)) C[x]+=delta; int query(int x) int tmp=0; for(;x>0;x-=lowbit(x)) tmp+=C[x]; return tmp; bool cmp(ques a,ques b) return a.r<b.r; void addedge(int u,int v) nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; void extend(int c,int id) if(t[last].ch[c]) int p=last; int q=t[p].ch[c]; if(t[q].len==t[p].len+1) last=q; else int nq=++tot; t[nq].len=t[p].len+1; t[nq].f=t[q].f,t[q].f=nq; memcpy(t[nq].ch, t[q].ch, sizeof(t[q].ch)); for(;p&&t[p].ch[c]==q;p=t[p].f) t[p].ch[c]=nq; last=nq; else int np=++tot,p=last; t[np].len=t[p].len+1,last=np; for(;p&&!t[p].ch[c];p=t[p].f) t[p].ch[c]=np; if(!p) t[np].f=1; else int q=t[p].ch[c]; if(t[q].len==t[p].len+1) t[np].f=q; else int nq=++tot; t[nq].len=t[p].len+1; t[nq].f=t[q].f,t[q].f=t[np].f=nq; memcpy(t[nq].ch, t[q].ch, sizeof(t[q].ch)); for(;p&&t[p].ch[c]==q;p=t[p].f) t[p].ch[c]=nq; t[last].v.push_back(id); void dfs(int u) dfn[u]=st[u]=++tim; for(int i=hd[u];i;i=nex[i]) int v=to[i]; dfs(v); for(int k=0;k<t[u].v.size();++k) G[dfn[u]].push_back(t[u].v[k]); ed[u]=tim; int main() last=tot=1; int i,j,n,m,k; // setIO("input"); scanf("%d%d",&n,&m); for(i=1;i<=n;++i) last=1; scanf("%s",S+1); int len=strlen(S+1); for(j=1;j<=len;++j) extend(S[j]-‘a‘,i); for(i=2;i<=tot;++i) addedge(t[i].f,i); dfs(1); for(i=1;i<=m;++i) scanf("%s",S+1); int len=strlen(S+1),p=1; for(j=1;j<=len;++j) int c=S[j]-‘a‘; if(!t[p].ch[c]) p=-1; break; else p=t[p].ch[c]; if(p!=-1) q[++cnt]=ques(st[p],ed[p],i); sort(q+1,q+1+cnt,cmp); for(j=i=1;i<=cnt;++i) for(;j<=q[i].r;++j) for(k=0;k<G[j].size();++k) int tt=G[j][k]; if(lst[tt]) update(lst[tt],-1); lst[tt]=j; update(j,1); answer[q[i].id]=query(q[i].r)-query(q[i].l-1); for(i=1;i<=m;++i) printf("%d\n",answer[i]); return 0;
以上是关于luogu SP8093 后缀自动机+树状数组+dfs序的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ2780[Spoj]8093 Sevenk Love Oimaster 广义后缀自动机
bzoj2780[Spoj]8093 Sevenk Love Oimaster 广义后缀自动机