AC自动机+树链剖分HDU 5566
Posted uuuxxllj
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AC自动机+树链剖分HDU 5566相关的知识,希望对你有一定的参考价值。
离线做法
对给出的树作树剖
把每个询问区间先加入线段树的结点
后对线段树每个有询问的节点建立AC自动机
对每个节点单独询问
1 // #include <bits/stdc++.h> 2 #include <iostream> 3 #include <cstdio> 4 #include <queue> 5 #include <cstring> 6 #include <cctype> 7 #include <algorithm> 8 #define For(i,a,b) for(int i=a;i<=b;++i) 9 #define Dec(i,b,a) for(int i=b;i>=a;--i) 10 #define file() freopen("c://users/asus/desktop/v.txt","r",stdin); 11 #define inf 0x3f3f3f3f 12 using namespace std; 13 14 typedef long long ll; 15 inline ll qr(){ 16 ll x=0,f=1; char ch; 17 while(!isdigit(ch=getchar())) if(ch==‘-‘) f=-1; 18 for(;isdigit(ch);x=x*10+ch-48,ch=getchar()); 19 return x*f; 20 } 21 // #define cmax(x,y) (x<y?x=y:0) 22 #define mid (l+r>>1) 23 #define lc x<<1 24 #define rc x<<1|1 25 const int N = 100010; 26 void cmax(int &x,int y){if(x<y) x=y;} 27 struct ACA { 28 int c[N][26],f[N],w[N],len[N],ct; 29 void clr(int x) { 30 memset(c[x],0,sizeof c[x]); 31 w[x]=len[x]=f[x]=0; 32 } 33 void init() {clr(ct=0); } 34 void ins(string s) 35 { 36 int u=0; 37 for(int i=0;i<s.length();++i) 38 { 39 int v=s[i]-‘a‘; 40 if(!c[u][v]) c[u][v]=++ct,clr(ct); 41 u=c[u][v]; 42 } 43 w[u]=1; 44 len[u]=s.length(); 45 } 46 void getfail() 47 { 48 queue<int> q; 49 For(i,0,25) if(c[0][i]) q.push(c[0][i]); 50 while(!q.empty()) 51 { 52 int u=q.front(); q.pop(); 53 For(i,0,25) 54 { 55 int &v=c[u][i]; 56 if(v) f[v]=c[f[u]][i],q.push(v),cmax(len[v],len[f[v]]); 57 else v=c[f[u]][i]; 58 } 59 } 60 } 61 int qry(string s) 62 { 63 int res=0,u=0; 64 for(int i=0;i<s.length();++i) 65 { 66 u=c[u][s[i]-‘a‘]; 67 cmax(res,len[u]); 68 } 69 return res; 70 } 71 } aca; 72 73 string s[N],t[N]; 74 int ans[N],n,m,idx; 75 vector<int> a[N<<2],g[N]; 76 int sz[N],d[N],fa[N],son[N],b[N],id[N],top[N]; 77 78 void build(int x,int l,int r) 79 { 80 a[x].clear(); 81 if(l==r) return; 82 build(lc,l,mid); build(rc,mid+1,r); 83 } 84 void qry(int x,int l,int r,int L,int R,int k) 85 { 86 if(L<=l&&r<=R) return(void)(a[x].push_back(k)); 87 if(L<=mid) qry(lc,l,mid,L,R,k); 88 if(R>mid) qry(rc,mid+1,r,L,R,k); 89 } 90 void getans(int x,int l,int r) 91 { 92 if(a[x].size()) 93 { 94 aca.init(); 95 For(i,l,r) aca.ins(s[b[i]]); 96 aca.getfail(); 97 for(int i=0;i<a[x].size();++i) 98 cmax(ans[a[x][i]],aca.qry(t[a[x][i]])); 99 } 100 if(l==r) return; 101 getans(lc,l,mid); getans(rc,mid+1,r); 102 } 103 void init() 104 { 105 idx=0; 106 fill(son,son+1+n,0); 107 For(i,1,n) g[i].clear(); 108 } 109 110 void dfs1(int u,int ff) 111 { 112 sz[u]=1; d[u]=d[ff]+1; fa[u]=ff; 113 for(int i=0,v;i<g[u].size();++i) 114 { 115 if((v=g[u][i])==ff) continue; 116 dfs1(v,u); sz[u]+=sz[v]; 117 if(sz[v]>sz[son[u]]) son[u]=v; 118 } 119 } 120 void dfs2(int u,int tp) 121 { 122 id[u]=++idx; b[idx]=u; top[u]=tp; 123 if(!son[u]) return; 124 dfs2(son[u],tp); 125 for(int i=0,v;i<g[u].size();++i) 126 if((v=g[u][i])!=fa[u] && v!=son[u]) dfs2(v,v); 127 } 128 void qrypath(int x,int y,int k) 129 { 130 while(top[x]!=top[y]) 131 { 132 if(d[top[x]]<d[top[y]]) swap(x,y); 133 qry(1,1,n,id[top[x]],id[x],k); 134 x=fa[top[x]]; 135 } 136 if(d[x]>d[y]) swap(x,y); 137 qry(1,1,n,id[x],id[y],k); 138 } 139 int main() 140 { 141 // file(); 142 ios::sync_with_stdio(0); 143 int kase; 144 cin >> kase; 145 while(kase--) 146 { 147 cin >> n; int x,y; 148 build(1,1,n); 149 init(); 150 For(i,1,n) cin >> s[i]; 151 For(i,2,n) 152 { 153 cin >> x; 154 g[x].push_back(i); 155 g[i].push_back(x); 156 } 157 dfs1(1,0); dfs2(1,1); 158 cin >> m; 159 For(i,1,m) 160 { 161 cin >> x >> y >> t[i]; 162 qrypath(x,y,i); 163 } 164 memset(ans,0,sizeof ans); 165 getans(1,1,n); 166 For(i,1,m) cout << ans[i] << endl; 167 } 168 return 0; 169 }
以上是关于AC自动机+树链剖分HDU 5566的主要内容,如果未能解决你的问题,请参考以下文章
hdu 2586 How far away?(树链剖分+前缀和)
[HDU5029]Relief grain(树链剖分+线段树)