[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自动机_倍增的主要内容,如果未能解决你的问题,请参考以下文章