# Clarke and room

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 11    Accepted Submission(s): 3

Problem Description
Clarke is a patient with multiple personality disorder. One day, Clarke split into n guys, the ith Clarke named namei
They live in n rooms connected by n1 roads. There is only one path between any two rooms. Now, their landlord is to check the name with a long list. The landlord will check m times, at ith time, he wants to know the maximum length of the names which appear on the list si on the path between xi and yirooms(including xi and yi).

Input
The first line contains an integer T(1T10), the number of test cases.
For each test case:
The first line contains an integer n(1n100000)
Then n lines follow, the ith line contains a string namei
Then n1 lines follow, the ith line contains an integer fi+1(1fi+1i), denoting there is an edge between i+1 and fi+1
Then m lines follow, the ith line contains two integers xi,yi(1xi,yin) and a string si
Every string is composed by lower letter.
1|namei|,|si|,ni=1|namei|,mi=1|si|100000

Output
For each test case, print m lines with the answers.

Sample Input
1 4 a ab abc d 1 2 1 3 1 1 abc 1 1 d 1 3 abc

Sample Output
1 0 3 Hint: Ask 1: $a$ appears in $abc$, so the answer is $1$. Ask 2: There is no one appears in $d$, so the answer is $0$. Ask 3: $a$, $ab$ and $abc$ appear in $abc$, so the answer is $3$.

代码如下，函数名字已经很清楚说明了函数功能

#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <queue>

using namespace std;

const int N = 26;
const int maxn = 100008;

int n, p[maxn], fp[maxn];

inline void mymax(int &x, int y){
if(y > x) x = y;
}

struct tire{
int nxt[N + 2], fail, is, len;
void init(){
memset(nxt, 0, sizeof(nxt));
fail = is = len = 0;
}
};

struct act{
tire t[maxn];
int root = 0, all;

void init(){
t[all = 0].init();
}
void insert(string s){
int now = 0;

for(int i = 0; i < (int)s.length(); i++){
int cc = s[i] - 'a';
if(!t[now].nxt[cc]){
t[now].nxt[cc] = ++all;
t[all].init();
}
now = t[now].nxt[cc];
}
t[now].is = 1;
t[now].len = s.length();
}
void build(){
int now = 0;
queue<int> q;

for(int i = 0; i < N; i++){
if(!t[now].nxt[i]) continue;
else{
t[t[now].nxt[i]].fail = 0;
q.push(t[now].nxt[i]);
}
}
while(!q.empty()){
now = q.front();
q.pop();
for(int i = 0; i < N; i++){
if(!t[now].nxt[i]){
t[now].nxt[i] = t[t[now].fail].nxt[i];
}
else{
t[t[now].nxt[i]].fail = t[t[now].fail].nxt[i];
mymax(t[t[now].nxt[i]].len, t[t[t[now].nxt[i]].fail].len);
q.push(t[now].nxt[i]);
}
}
}
}
int run(string s){
int res = 0, now = 0;

for(int i = 0; i < (int)s.length(); i++){
int cc = s[i] - 'a';
now = t[now].nxt[cc];
mymax(res, t[now].len);
}

return res;
}
}ac;

string s[maxn], ans[maxn];
int res[maxn];

struct segtree{
vector<int> v[maxn << 2];

void init(int pos, int l, int r){
v[pos].clear();
if(l == r) return ;
int mid = (l + r) >> 1;
init(pos << 1, l, mid);
init(pos << 1 | 1, mid + 1, r);
}
void query(int pos, int l, int r, int tl, int tr, int vv){
if(tl <= l && r <= tr){
v[pos].push_back(vv);
return ;
}
int mid = (l + r) >> 1;
if(tr <= mid){
query(pos << 1, l, mid, tl, tr, vv);
}
else if(tl > mid){
query(pos << 1 | 1, mid + 1, r, tl, tr, vv);
}
else{
query(pos << 1, l, mid, tl, mid, vv);
query(pos << 1 | 1, mid + 1, r, mid + 1, tr, vv);
}
}
void getans(int pos, int l, int r){
if(v[pos].size()){
//printf("pos  %d   %d   %d\n", pos, l, r);
ac.init();
for(int i = l; i <= r; i++){
ac.insert(s[fp[i]]);
}
ac.build();
for(int i = 0; i < (int)v[pos].size(); i++){
mymax(res[v[pos][i]], ac.run(ans[v[pos][i]]));
}
}
if(l == r) return ;
int mid = (l + r) >> 1;
getans(pos << 1, l, mid);
getans(pos << 1 | 1, mid + 1, r);
}
}st;

struct edge{
int to, nxt;
};

struct slpf{
edge e[maxn << 2];
int deep[maxn], num[maxn];
int son[maxn], tot, pos, root;

void init(){
tot = 0;
pos = 1;
memset(son, -1, sizeof(son));
}
e[tot].to = v;
}
void dfs1(int u, int pre, int d){
deep[u] = d;
fa[u] = pre;
num[u] = 1;
for(int i = head[u]; i != -1; i = e[i].nxt){
int v = e[i].to;
if(v != pre){
dfs1(v, u, d + 1);
num[u] += num[v];
if(son[u] == -1 || num[v] > num[son[u]])
son[u] = v;
}
}
}
void getpos(int u, int sp){
top[u] = sp;
p[u] = pos++;
fp[p[u]] = u;
if(son[u] == -1) return ;
getpos(son[u], sp);
for(int i = head[u]; i != -1; i = e[i].nxt){
int v = e[i].to;
if(v != son[u] && v != fa[u])
getpos(v, v);
}
}
void build(){
dfs1(1, 0, 0);
getpos(1, 1);
}
void query(int u, int v, int vv){
int f1 = top[u], f2 = top[v];

while(f1 != f2){
if(deep[f1] < deep[f2]){
swap(f1, f2);
swap(u, v);
}
st.query(1, 1, n, p[f1], p[u], vv);
//printf("query   %d   %d\n", p[f1], p[u]);
u = fa[f1];
f1 = top[u];
}
if(deep[u] > deep[v]) swap(u, v);
st.query(1, 1, n, p[u], p[v], vv);
}
}spt;

int main(){
int _, x, y, m;

//freopen("in.txt", "r", stdin);
ios::sync_with_stdio(0);
cin >> _;
while(_--){
cin >> n;
st.init(1, 1, n);
spt.init();
for(int i = 1; i <= n; i++){
cin >> s[i];
}
for(int i = 1; i < n; i++){
cin >> x;
}
spt.build();
cin >> m;
for(int i = 1; i <= m; i++){
cin >> x >> y >> ans[i];
spt.query(x, y, i);
}
memset(res, 0, sizeof(res));
st.getans(1, 1, n);
for(int i = 1; i <= m; i++){
cout << res[i] << endl;
}
}

return 0;
}


• 本文已收录于以下专栏：

## 【HDU】5566 Clarke and room【树链剖分+AC自动机】

• u013368721
• 2016年11月01日 11:09
• 495

## hdu 5566 Clarke and room ac自动机+树链剖分+主席树

#include #include #include #include #include #include using namespace std; #define N 100020 #...
• u013654696
• 2016年01月20日 21:02
• 347

## HDU 3695 AC自动机 裸题

• qq574857122
• 2013年10月06日 22:57
• 2002

## HDU 4787 GRE Words Revenge（在线AC自动机）

• u014357885
• 2015年09月10日 21:54
• 812

## HDU 2296 Ring(AC自动机+DP)

HDU 2296 Ring(AC自动机+DP) http://acm.hdu.edu.cn/showproblem.php?pid=2296 题意:给你M个单词构成一个词典,每个单词有一个权值(单词出...
• u013480600
• 2014年04月13日 12:23
• 1168

## hdu2296 Ring (AC自动机+dp)

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission...
• Kirito_Acmer
• 2016年02月11日 16:57
• 416

## HDU 6086 AC自动机+状压dp

• Bahuia
• 2017年08月13日 19:48
• 478

## hdu5384(AC自动机+纪录重复单词出现的次数)

• ms961516792
• 2015年08月13日 16:29
• 483

## HDU 5069 Harry And Biological Teacher AC自动机 + 线段树优化 (BestCoder Round 14 D)

• u013738743
• 2015年05月28日 15:44
• 770

## AC自动机模板（数组+指针）hdu2222

Online Judge Online Exercise Online Teaching Online Contests Exercise Author F.A.Q Hand In...
• u010660276
• 2014年08月20日 17:01
• 531

举报原因： 您举报文章：hdu 5566 Clarke and room（ac自动机+树链剖分） 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)