// begin {AC auto machine}const int MAXN_NODE = 5e5 + 7;const int MAXN_CHAR = 128;int ch[MAXN_NODE][MAXN_CHAR], fail[MAXN_NODE], val[MAXN_NODE], last[MAXN_NODE], sz;inline int idx(char c) {return (int)c;}void insert(char *s, int v) { int u = 0, n = strlen(s); for(int i = 0; i < n; ++i) { int c = idx(s[i]); if(!ch[u][c]) { memset(ch[sz], 0, sizeof(ch[sz])); //val[sz] = 0; ch[u][c] = sz++; } u = ch[u][c]; } val[u] = v;}std::queue q;void get_fail() { fail[0] = 0; for(int c = 0; c < MAXN_CHAR; ++c) { int u = ch[0][c]; if(u) {fail[u] = 0; q.push(u), last[u] = 0;} } // BFS while(!q.empty()) { int r = q.front(); q.pop(); for(int c = 0; c < MAXN_CHAR; ++c) { int u = ch[r][c]; if(!u) {ch[r][c] = ch[fail[r]][c]; continue;} q.push(u); int v = fail[r]; while(v && !ch[v][c]) v = fail[v]; fail[u] = ch[v][c]; last[u] = val[fail[u]] ? fail[u] : last[fail[u]]; } }}void print(int j) { if(j) { //printf("%d:%d\n",j,val[j]); print(last[j]); ans[val[j]] ++; }}void find(char *T) { int n = strlen(T), j = 0; for(int i = 0; i < n; ++i) { int c = idx(T[i]); j = ch[j][c]; if(val[j]) print(j); else if(last[j]) print(last[j]); }}void init() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); memset(val, 0, sizeof(val));}// end {AC auto machine}
下面代码针对频繁调用 print 进行了优化,没有立即沿suffix link 更新,而是最后自底向根root更新统计值
// begin {ac-automation}const int MAXN = 3e5 + 7;const int SIGMA_SIZE = 26;struct ac_automation { struct node {int next[SIGMA_SIZE], fail, val;}; node nod[MAXN]; int length, pos[MAXN], st[MAXN], top; inline void init() { length = top = 0; newNode(); } inline int newNode() { node &p = nod[length]; p.val = p.fail = 0; memset(p.next, 0, SIGMA_SIZE * 4); return length++; } inline int idx(char c) {return c - 'a';} void insert(char *s, int id) { int cur = 0, k ; for(; *s; ++s) { k = idx(s[0]); node &p = nod[cur]; if(!p.next[k]) p.next[k] = newNode(); cur = p.next[k]; } pos[id] = cur; } std::queue Q; void get_fail() { int cur = 0; for(register int i = 0; i < SIGMA_SIZE; ++i) { node &p = nod[cur]; if(p.next[i]) Q.push(p.next[i]); } while(!Q.empty()) { cur = Q.front(); Q.pop(); for(int i = 0; i < SIGMA_SIZE; ++i) { node &p = nod[cur]; if(p.next[i]) { int &e = p.next[i], &j = p.fail; nod[e].fail = nod[j].next[i]; Q.push(e); st[++top] = e; } else p.next[i] = nod[p.fail].next[i]; } } } void find(char *s) { int now = 0; for(; *s; ++s) { int k = idx(s[0]); now = nod[now].next[k]; nod[now].val ++; } int tmp = top, p; while(tmp) { p = st[tmp]; nod[nod[p].fail].val += nod[p].val; tmp --; } }};// end {ac-automation}
LightOJ 1427 Substring Frequency (II)
题目链接:
给出的模板串会有重复,记录每个串在 \(Trie\) 中的位置 pos , \(Trie\) 中节点统计有次数 \(val\) 输出即可
#include #include #include #include // begin {ac-automation}const int MAXN = 3e5 + 7;const int SIGMA_SIZE = 26;struct ac_automation { struct node {int next[SIGMA_SIZE], fail, val;}; node nod[MAXN]; int length, pos[MAXN], st[MAXN], top; inline void init() { length = top = 0; newNode(); } inline int newNode() { node &p = nod[length]; p.val = p.fail = 0; memset(p.next, 0, sizeof(p.next)); return length++; } inline int idx(char c) {return c - 'a';} void insert(char *s, int id) { int cur = 0, k ; for(; *s; ++s) { k = idx(s[0]); node &p = nod[cur]; if(!p.next[k]) p.next[k] = newNode(); cur = p.next[k]; } pos[id] = cur; } std::queue Q; void get_fail() { int cur = 0; for(register int i = 0; i < SIGMA_SIZE; ++i) { node &p = nod[cur]; if(p.next[i]) Q.push(p.next[i]); } while(!Q.empty()) { cur = Q.front(); Q.pop(); for(int i = 0; i < SIGMA_SIZE; ++i) { node &p = nod[cur]; if(p.next[i]) { int &e = p.next[i], &j = p.fail; nod[e].fail = nod[j].next[i]; Q.push(e); st[++top] = e; } else p.next[i] = nod[p.fail].next[i]; } } } void find(char *s) { int now = 0; for(; *s; ++s) { int k = idx(s[0]); now = nod[now].next[k]; nod[now].val ++; } int tmp = top, p; while(tmp) { p = st[tmp]; nod[nod[p].fail].val += nod[p].val; tmp --; } }};// end {ac-automation}ac_automation ac;const int MAX_t = 1e6 + 7;char t[MAX_t], s[500 + 7];int main() { int T, n; scanf("%d", &T); for(int i = 0; i < T; ++i) { ac.init(); scanf("%d", &n); getchar(); gets(t); for(int j = 0; j < n; ++j) { gets(s); ac.insert(s, j + 1); } ac.get_fail(); ac.find(t); printf("Case %d:\n", i + 1); for(int j = 0; j < n; ++j) printf("%d\n", ac.nod[ac.pos[j + 1]].val); } return 0;}
HDU-2896 病毒侵袭
#include #include #include #include #include std::bitset<500+7>vis;// begin{Ac_Automation}const int max_node = 5e5 + 7;const int sigma_size = 128;int ch[max_node][sigma_size], val[max_node], sz;int fail[max_node], last[max_node];inline int idx(char c) {return (int)c;}void insert(char *s, int v = 1) { int u = 0, n = strlen(s); for(int i = 0; i < n; ++i) { int c = idx(s[i]); if(!ch[u][c]) { memset(ch[sz], 0, sizeof(ch[sz])); //val[sz] = 0; ch[u][c] = sz++; } u = ch[u][c]; } val[u] = v;}std::queue q;void get_fail() { fail[0] = 0; for(int c = 0; c < sigma_size; ++c) { int u = ch[0][c]; if(u) {fail[u] = 0; q.push(u), last[u] = 0;} } // BFS while(!q.empty()) { int r = q.front(); q.pop(); for(int c = 0; c < sigma_size; ++c) { int u = ch[r][c]; if(!u) {ch[r][c] = ch[fail[r]][c]; continue;} q.push(u); int v = fail[r]; while(v && !ch[v][c]) v = fail[v]; fail[u] = ch[v][c]; last[u] = val[fail[u]] ? fail[u] : last[fail[u]]; } }}void print(int j) { if(j) { //printf("%d:%d\n",j,val[j]); print(last[j]); vis[val[j]] = true;; }}void find(char *T) { int n = strlen(T), j = 0; for(int i = 0; i < n; ++i) { int c = idx(T[i]); j = ch[j][c]; if(val[j]) print(j); else if(last[j]) print(last[j]); }}void init() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); memset(val, 0, sizeof(val));}// end{Ac_Automation}char s[10000007];void solve() { init(); int n; scanf("%d", &n); getchar(); for(int i = 0; i < n; i++) {gets(s); insert(s, i + 1);} get_fail(); int ret = 0; scanf("%d", &n); getchar(); for(int i = 0; i < n; ++i) { gets(s);vis.reset();find(s); if(vis.any()) { printf("web %d:", i + 1); ret++; for(int j = 0; j < 500; ++j) { if(vis[j+1]) printf(" %d", j+1); } puts(""); } } printf("total: %d\n", ret);}int main() {solve(); return 0;}
POJ - 2778 DNA Sequence
#pragma comment(linker, "/STACK:36777216")//#pragma GCC optimize ("O2")#define LOCAL//#include "testlib.h"#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include
上面是岛娘的代码,真心快呀,改天好好学习下