ac自动机fail树上dfs序建可持久化线段树
Posted 20203246
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ac自动机fail树上dfs序建可持久化线段树相关的知识,希望对你有一定的参考价值。
#include <cstring> #include <cstdio> #define max(a,b) a>b?a:b const int mn=300005; struct Trie{ int father,fail,next[26]; void init(){ father=fail=0; memset(next,0,sizeof next); } }tree[mn]; struct Xls{ int size,y[mn],nxt[mn],fst[mn]; void set(){ size=0; memset(fst,0,sizeof fst); } void add(int a,int b){ y[++size]=b; nxt[size]=fst[a]; fst[a]=size; } }g; struct Segtree{ int val,add,l,r; }segtree[mn*4]; char str[mn]; int pos[mn],n,cnt,val[21000],in[mn],out[mn]; void build(char ch[]){ int rt=1,t,len=strlen(ch); for (int i=0;i<len;i++){ t=ch[i]-\'a\'; if (!tree[rt].next[t]){ tree[++cnt].init(); tree[rt].next[t]=cnt; } tree[tree[rt].next[t]].father=rt; rt=tree[rt].next[t]; } } int q[310000]; void build_AC(){ int head=0,tail=0,rt,son,k; q[++tail]=1;tree[0].fail=1; while (head<tail){ rt=q[++head]; for (int i=0;i<26;i++){ son=tree[rt].next[i]; if (!son){ tree[rt].next[i]=tree[tree[rt].fail].next[i]; continue; } k=tree[rt].fail; while (!tree[k].next[i]) k=tree[k].fail; tree[son].fail=tree[k].next[i]; q[++tail]=son; } } g.set(); for (int i=1;i<=cnt;i++) g.add(tree[i].fail,i); } int count_dfs; void dfs(int rt){ in[rt]=++count_dfs; for (int i=g.fst[rt];i;i=g.nxt[i]) dfs(i); out[rt]=count_dfs; } void buildseg(int rt,int le,int ri){ segtree[rt].val=segtree[rt].add=0; segtree[rt].l=le;segtree[rt].r=ri; if (le==ri) return; buildseg(rt<<1,le,(le+ri)>>1); buildseg(rt<<1|1,((le+ri)>>1)+1,ri); } void pushdown(int rt){ if (segtree[rt].add){ segtree[rt<<1].add=max(segtree[rt<<1].add,segtree[rt].add); segtree[rt<<1].val=max(segtree[rt<<1].val,segtree[rt].add); segtree[rt<<1|1].add=max(segtree[rt<<1|1].add,segtree[rt].add); segtree[rt<<1|1].val=max(segtree[rt<<1|1].val,segtree[rt].add); segtree[rt].add=0; } } int query(int rt,int x){ if (segtree[rt].l==segtree[rt].r) return segtree[rt].val; pushdown(rt); if (x<=segtree[rt<<1].r) return query(rt<<1,x); else return query(rt<<1|1,x); } int XLE,XRI,Xval; void update(int rt){ if (segtree[rt].l>XRI||segtree[rt].r<XLE) return; if (XLE<=segtree[rt].l&&segtree[rt].r<=XRI){ segtree[rt].val=max(segtree[rt].val,Xval); segtree[rt].add=max(segtree[rt].add,Xval); return; } pushdown(rt); update(rt<<1); update(rt<<1|1); segtree[rt].val=max(segtree[rt<<1].val,segtree[rt<<1|1].val); } int solve(){ int rt,t,big,result=0; for (int i=1;i<=n;i++){ rt=1;big=0; for (int j=pos[i-1];j<pos[i];j++){ t=str[j]-\'a\'; rt=tree[rt].next[t]; big=max(big,query(1,in[rt])); } XLE=in[rt];XRI=out[rt];Xval=big+val[i]; update(1); result=max(result,Xval); } return result; } int main(){ int T; scanf("%d",&T); for (int Case=1;Case<=T;Case++){ memset(str,0,sizeof str); memset(pos,0,sizeof pos); cnt=1; tree[0].init(); tree[1].init(); for (int i=0;i<26;i++) tree[0].next[i]=1; scanf("%d",&n); for (int i=1;i<=n;i++){ scanf("%s%d",str+pos[i-1],&val[i]); build(str+pos[i-1]); pos[i]=pos[i-1]+strlen(str+pos[i-1]); } build_AC(); count_dfs=0; dfs(1); buildseg(1,1,count_dfs); printf("Case #%d: %d\\n",Case,solve()); } return 0; }
以上是关于ac自动机fail树上dfs序建可持久化线段树的主要内容,如果未能解决你的问题,请参考以下文章
HDU4117 GRE WORDS(AC自动机+线段树维护fail树的dfs序)