【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 }

原文地址:https://www.cnblogs.com/uuuxxllj/p/10885281.html

时间: 2024-10-14 04:50:31

【AC自动机+树链剖分】HDU 5566的相关文章

树链剖分 [HDU 3966] Aragorn&#39;s Story

Aragorn's Story Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3544    Accepted Submission(s): 995 Problem Description Our protagonist is the handsome human prince Aragorn comes from The Lord

树链剖分 [HDU 5029] Relief grain

Relief grain Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others) Total Submission(s): 1254    Accepted Submission(s): 299 Problem Description The soil is cracking up because of the drought and the rabbit kingdom is

[LuoguU41039]PION后缀自动机 树链剖分

链接 刚开始看出题人题解都吓蒙掉了,还以为是什么难题,结果就一板子题 思路:对每一个文件名开一棵线段树,然后树剖即可 #include<bits/stdc++.h> #define REP(i,a,b) for(int i(a);i<=(b);++i) #define dbg(...) fprintf(stderr,__VA_ARGS__) using namespace std; typedef long long ll; typedef unsigned int uint; type

树链剖分 [HDU 5044] Tree

Tree Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2038    Accepted Submission(s): 391 Problem Description You are given a tree (an acyclic undirected connected graph) with N nodes. The tree

Hdu 3966 Aragorn&#39;s Story (树链剖分 + 线段树区间更新)

题目链接: Hdu 3966 Aragorn's Story 题目描述: 给出一个树,每个节点都有一个权值,有三种操作: 1:( I, i, j, x ) 从i到j的路径上经过的节点全部都加上x: 2:( D, i, j, x ) 从i到j的路径上经过的节点全部都减去x: 3:(Q, x) 查询节点x的权值为多少? 解题思路: 可以用树链剖分对节点进行hash,然后用线段树维护(修改,查询),数据范围比较大,要对线段树进行区间更新 1 #include <cstdio> 2 #include

HDU 5044 (树链剖分+树状数组+点/边改查)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5044 题目大意:修改链上点,修改链上的边.查询所有点,查询所有边. 解题思路: 2014上海网赛的变态树链剖分模板题.将以往树链剖分的点&边修改和查询合在一起之后,难度上去不少. 第一个卡人点是读入优化. 第二个卡人点是树状数组.由于要查询所有点,如果使用线段树,每次都要扫到底层才能取出点值,必T无疑. 然后使用树状数组之后,树链剖分的点/边修改写法有些变动. 点查询变化不大. 边查询只要查询一下

Hdu 3699 Aragorn&#39;s Story (树链剖分)

题目大意: 对一颗树上进行路径加减,然后询问单点的值. 思路分析: 简单的树链剖分模板题. #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #pragma comment(linker,"/STACk:10240000,10240000") #define maxn 50005 #define lson num<<1,s

hdu 5893 (树链剖分+合并)

List wants to travel Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 429    Accepted Submission(s): 92 Problem Description A boy named List who is perfect in English. Now he wants to travel an

HDU 5044 Tree(树链剖分)

HDU 5044 Tree 题目链接 就简单的树链剖分,不过坑要加输入外挂,还要手动扩栈 代码: #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; const int N = 100005; #pragma comment(linker, "/STACK:1024000000,1024000000"