[JSOI 2012] 玄武密码
Posted evenbao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[JSOI 2012] 玄武密码相关的知识,希望对你有一定的参考价值。
[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=4327
[算法]
AC自动机
[代码]
#include<bits/stdc++.h> using namespace std; const int MAXN = 1e7 + 10; const int MAXM = 1e5 + 10; const int MAXLEN = 110; int n,m; int ans[MAXM]; char P[MAXN]; char s[MAXM][MAXLEN]; inline int get_value(char a) { if (a == ‘E‘) return 0; if (a == ‘S‘) return 1; if (a == ‘W‘) return 2; if (a == ‘N‘) return 3; } struct AC_Automation { int tot; int root; struct Node { int child[4]; int fail; bool visited; } trie[MAXN]; inline void insert(char *s) { int now = root; int len = strlen(s + 1); for (int i = 1; i <= len; i++) { int val = get_value(s[i]); if (!trie[now].child[val]) trie[now].child[val] = ++tot; now = trie[now].child[val]; } } inline void rebuild() { int l,r; static int q[MAXN]; q[l = r = 1] = root; trie[root].fail = -1; while (l <= r) { int cur = q[l]; l++; for (int i = 0; i < 4; i++) { if (trie[cur].child[i]) { if (cur == root) trie[trie[cur].child[i]].fail = 0; else { int p = trie[cur].fail; while (p != -1) { if (trie[p].child[i]) { trie[trie[cur].child[i]].fail = trie[p].child[i]; break; } else p = trie[p].fail; } } q[++r] = trie[cur].child[i]; } } } } inline void getans(char *s) { int now = root; int len = strlen(s + 1); for (int i = 1; i <= len; i++) { int val = get_value(s[i]); int p = now; while (p != -1) { if (trie[p].child[val]) break; else p = trie[p].fail; } if (p == -1) { now = 0; continue; } else now = p = trie[p].child[val]; while (p) { if (!trie[p].visited) { trie[p].visited = true; p = trie[p].fail; } else break; } } } inline void calc(int pos,char *s) { int now = root; int len = strlen(s + 1); for (int i = 1; i <= len; i++) { int val = get_value(s[i]); now = trie[now].child[val]; if (trie[now].visited) ans[pos] = i; } } } ACAM; int main() { scanf("%d%d",&n,&m); scanf("%s",P + 1); for (int i = 1; i <= m; i++) scanf("%s",s[i] + 1); for (int i = 1; i <= m; i++) ACAM.insert(s[i]); ACAM.rebuild(); ACAM.getans(P); for (int i = 1; i <= m; i++) ACAM.calc(i,s[i]); for (int i = 1; i <= m; i++) printf("%d ",ans[i]); return 0; }
以上是关于[JSOI 2012] 玄武密码的主要内容,如果未能解决你的问题,请参考以下文章