hdu 5566 Clarke and room(ac自动机+树链剖分)

原创 2015年11月17日 16:22:38

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$.

题意:给一棵n个点的树,每个节点有一个串,然后有m个查询x y s,查询点x走到点y路径上(包含x,y)的串是s的子串的最长的长度是多少

题解:这题我用的是离线的方法,首先熟练剖分作查询,然后标记好线段树的每个点被哪些查询访问,最后单独对每个存在查询的线段树结点建立一棵自动机,把这个线段树结点包含的区间的串全部插入自动机,然后对逐一对访问过这个区间的串作一次查询更新对应查询。复杂度是(name + s)* logn * logn级别的

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


#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 head[maxn], top[maxn], fa[maxn];
	int deep[maxn], num[maxn];
	int son[maxn], tot, pos, root;

	void init(){
		tot = 0;
		memset(head, -1, sizeof(head));
		pos = 1;
		memset(son, -1, sizeof(son));
	}
	void addedge(int u, int v){
		e[tot].to = v;
		e[tot].nxt = head[u];
		head[u] = tot++;
	}
	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.addedge(i + 1, x);
			spt.addedge(x, i + 1);
		}
		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自动机+树链剖分+主席树

#include #include #include #include #include #include using namespace std; #define N 100020 #...

【HDU】5069 Harry And Biological Teacher AC自动机fail指针建树dfs

传送门:【HDU】5069 Harry And Biological Teacher 先扯淡:西安区域赛运气好拿了个银回来,但然后就是无尽的补作业+补题,生活如此艰难,何必非要拆穿TUT。。...

hdu 3341(ac自动机+状态压缩)

  • 2013年10月29日 17:03
  • 23KB
  • 下载

一篇关于AC自动机论文的译文:《Biosequence Algorithms, Spring 2005 Lecture 4: Set Matching and Aho-Corasick Algorit

之前初学AC自动机的时候看过一篇相当不错的论文   点这里。当时看完就觉得对AC自动机有了相当好的认识。现在我再来回顾这篇文章的时候,觉得应该做点翻译,加深个人理解的同时可以帮助一些没心情看英文论文的...

WHU1572---Cyy and Fzz (AC自动机+dp)

Description As Cyy and Fzz are both busy repairing the network, Sama feel a little boring because i...

【AC自动机】 HDOJ 5069 Harry And Biological Teacher

#include #include #include #include #include #include #include #include #include #i...

WHU 1572 Cyy and Fzz(AC自动机+dp)

题意:给出n个模板串,随机一个串,求出现模板串个数的期望(相同算一个)。 做法:比赛时误以为是求模板串出现了几次,用dp[i][j]代表在第i个节点还要走l步的期望,然后记忆化搜索。。不停的wa。。 ...

hdu 5955 Guessing the Dice Roll 概率DP,ac自动机,高斯消元 ★★

掷骰子,n个人,每人预测一个长度为L的序列,直至筛子序列的最后L个数与某个人预测的一致为止游戏结束(每个人预测的序列不一样,且长度均为L)。...

HDU 3065 病毒侵袭持续中(AC自动机)

解题思路: 跟上一题类似,仍然是AC自动机的简单应用,记录一下每个串出现的次数即可。、 #include #include #include #include #include #inc...

HDU 4511 小明系列故事——女友的考验 (AC自动机+DP)

题意:   终于放寒假了,小明要和女朋友一起去看电影。这天,女朋友想给小明一个考验,在小明正准备出发的时候,女朋友告诉他,她在电影院等他,小明过来的路线必须满足给定的规则:   1、假设小明在的位置...
  • Ezereal
  • Ezereal
  • 2016年08月08日 09:19
  • 165
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:hdu 5566 Clarke and room(ac自动机+树链剖分)
举报原因:
原因补充:

(最多只允许输入30个字)