[bzoj2746][HEOI2012]旅行问题 _AC自动机_倍增

Posted shurak

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[bzoj2746][HEOI2012]旅行问题 _AC自动机_倍增相关的知识,希望对你有一定的参考价值。

[HEOI2012]旅行问题

题目链接https://www.lydsy.com/JudgeOnline/problem.php?id=2746


题解

这个是讲课时候的题。

讲课的时候都在想怎么后缀自动机....

当然是能做啦,$SAM$这么强。

实际上是个$AC$自动机,按照题目模拟就行了。

代码

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 1 << 20 ;

const int mod = 1000000007 ;

const int P = 21 ;

queue <int> Q;

int n, m, ch[N][26], fail[N][25], dep[N], tail, cnt, pos[N << 1], lenth[N];

char str[N];

ll Hash[N];

void insert() 
	int len = strlen(str);
	int p = 0;
	for (int i = 0; i < len; i ++ ) 
		int c = str[i] - ‘a‘;
		if (!ch[p][c]) 
			ch[p][c] = ++tail;
			Hash[ch[p][c]] = (((Hash[p] * 26) % mod) + c) % mod;
		
		pos[ ++ cnt] = ch[p][c]; 
		p = ch[p][c];
	   


void getfail() 
	dep[0] = 0;
	for (int i = 0; i < 26; i ++ ) 
		if (ch[0][i]) 
			fail[ch[0][i]][0] = 0;
			dep[ch[0][i]] = 1;
			Q.push(ch[0][i]);
		
	
	while (!Q.empty()) 
		int top = Q.front();
		Q.pop();
		for (int i = 0; i < 26; i ++ ) 
			if (!ch[top][i]) 
				ch[top][i] = ch[fail[top][0]][i];
				continue;
			
			int u = ch[top][i];
			fail[u][0] = ch[fail[top][0]][i];
			dep[u] = dep[fail[u][0]] + 1;
			for (int j = 1; j < P; j ++ ) 
				fail[u][j] = fail[fail[u][j - 1]][j - 1];
			
			Q.push(u);
		
	   


int getlca(int u, int v) 
	if (dep[u] < dep[v]) 
		swap(u, v);
	
	int d = dep[u] - dep[v];
	for (int i = 0; d; d >>= 1, i ++ ) 
		if (d & 1) 
			u = fail[u][i];
		
	
	if (u == v) 
		return u;
	
	for (int p = P - 1; p >= 0; p -- ) 
		if (fail[u][p] != fail[v][p]) 
			u = fail[u][p];
			v = fail[v][p];   
		
	   
	return fail[u][0];


int main() 
	scanf("%d", &n);
	memset(fail, 0, sizeof fail);
	lenth[0] = 0;
	for (int i = 1; i <= n; i ++ ) 
		scanf("%s", str);
		insert();
		lenth[i] = strlen(str);
		lenth[i] += lenth[i - 1];
	
	getfail();
	scanf("%d", &m);
	while (m -- ) 
		int p1, l1, p2, l2;
		scanf("%d%d%d%d", &p1, &l1, &p2, &l2);
		int t1 = pos[lenth[p1 - 1] + l1];
		int t2 = pos[lenth[p2 - 1] + l2];
		int lca = getlca(t1, t2);
		printf("%lld\n", Hash[lca]);
	
	return 0;

小结:注意一下AC自动机找LCA要倍增,别直接跳fail......

以上是关于[bzoj2746][HEOI2012]旅行问题 _AC自动机_倍增的主要内容,如果未能解决你的问题,请参考以下文章

HEOI 2012 旅行问题

旅行问题(bzoj 2746)

BZOJ2743: [HEOI2012]采花

BZOJ 2744: [HEOI2012]朋友圈

[bzoj2743][HEOI2012]采花(树状数组+离线)

bzoj2743[HEOI2012]采花