[Coci2015]Divljak
Posted liguanlin1124
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Coci2015]Divljak相关的知识,希望对你有一定的参考价值。
题目大意:
Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的。
接下来会发生q个操作,操作有两种形式:
“1 P”,Bob往自己的集合里添加了一个字符串P。
“2 x”,Alice询问Bob,集合T中有多少个字符串包含串S_x。(我们称串A包含串B,当且仅当B是A的子串)
Bob遇到了困难,需要你的帮助。
题解:
建出fail树然后搞树链的并……
(恶心)
正经的题解开始。
先建出关于S的trie树,把fail树建出来。
然后每读进来一个T,就把它放在trie树上走一边,然后把经过的点记录下来。
按dfs入栈序排序。
然后在dfs序上将每个点入栈时间打+1标记,将相邻点的lca打-1标记。
查询时直接tout-tin即可。
代码:
#include<queue> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 100050 #define M 2000050 int n,q,tot,tl[N]; char ch[M]; struct Trie { int ch[28],fl; }tr[M]; int hed[M],cnt; struct EG { int to,nxt; }e[M]; void ae(int f,int t) { e[++cnt].to = t; e[cnt].nxt = hed[f]; hed[f] = cnt; } void trie_pic() { queue<int>q; for(int i=1;i<=26;i++) if(tr[0].ch[i]) { q.push(tr[0].ch[i]); ae(0,tr[0].ch[i]); } while(!q.empty()) { int u = q.front(); q.pop(); for(int i=1;i<=26;i++) { int &v = tr[u].ch[i]; if(!v) { v = tr[tr[u].fl].ch[i]; continue; } tr[v].fl = tr[tr[u].fl].ch[i]; ae(tr[v].fl,v); q.push(v); } } } int tin[M],tout[M],tim,fa[M],son[M],siz[M],dep[M],top[M]; void dfs(int u) { tin[u]=++tim; siz[u]=1; for(int j=hed[u];j;j=e[j].nxt) { int to = e[j].to; fa[to]=u; dep[to]=dep[u]+1; dfs(to); siz[u]+=siz[to]; if(siz[to]>siz[son[u]]||!son[u])son[u]=to; } tout[u]=tim; } void dfs2(int u,int Top) { top[u]=Top; if(!son[u])return ; dfs2(son[u],Top); for(int j=hed[u];j;j=e[j].nxt) { int to = e[j].to; if(to!=son[u])dfs2(to,to); } } int get_lca(int x,int y) { while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]])swap(x,y); x=fa[top[x]]; } return dep[x]<dep[y]?x:y; } int f[M]; void up(int x,int d) { if(!x)return ; while(x<=2000000)f[x]+=d,x+=(x&(-x)); } int down(int x) { if(!x)return 0; int ret = 0; while(x)ret+=f[x],x-=(x&(-x)); return ret; } int sta[M],tal; bool cmp(int x,int y) { return tin[x]<tin[y]; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%s",ch+1); int len = strlen(ch+1),u=0; for(int j=1;j<=len;j++) { int c = ch[j]-‘a‘+1; if(!tr[u].ch[c])tr[u].ch[c]=++tot; u=tr[u].ch[c]; } tl[i]=u; } trie_pic(); dfs(0);dfs2(0,0); scanf("%d",&q); for(int opt,x,i=1;i<=q;i++) { scanf("%d",&opt); if(opt==1) { scanf("%s",ch+1); tal=0; int len = strlen(ch+1),u=0; for(int j=1;j<=len;j++) { u = tr[u].ch[ch[j]-‘a‘+1]; sta[++tal]=u; } sort(sta+1,sta+1+tal,cmp); for(int i=1;i<=tal;i++)up(tin[sta[i]],1); for(int i=1;i<tal;i++)up(tin[get_lca(sta[i],sta[i+1])],-1); }else { scanf("%d",&x); printf("%d ",down(tout[tl[x]])-down(tin[tl[x]]-1)); } } return 0; }
以上是关于[Coci2015]Divljak的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 3881 [Coci2015]Divljak——LCT维护parent树链并