AC自动机
百度文库搜trie图
利用安全图的概念可以做POJ2778
POJ2778
1 #include <cstdio> 2 #include <cstring> 3 const int p = 1e5; 4 int trie[170][4], map[255], fail[150], q[2000000], cnt; 5 bool v[170]; 6 struct M { 7 long long s[170][170]; 8 M () { memset (s, 0, sizeof s); } 9 }x, ans; 10 inline M operator * (const M & a, const M & b) 11 { 12 M c; 13 for (int i = 0; i <= cnt; i ++) 14 for (int j = 0; j <= cnt; j ++) 15 for (int k = 0; k <= cnt; k ++) 16 c.s[i][j] += a.s[i][k] * b.s[k][j], c.s[i][j] %= p; 17 return c; 18 } 19 inline void add (char * s) 20 { 21 int p = 0; 22 for (; * s; s ++) 23 { 24 if (trie[p][map[*s]] == 0) 25 trie[p][map[*s]] = ++ cnt; 26 p = trie[p][map[*s]]; 27 } 28 v[p] = true; 29 } 30 inline void build () 31 { 32 int h = 1, t = 2; 33 while (h < t) 34 { 35 int u = q[h ++]; 36 for (int i = 0; i < 4; i ++) 37 if (trie[u][i]) 38 { 39 if (u) 40 fail[trie[u][i]] = trie[fail[u]][i], v[trie[u][i]] |= v[trie[fail[u]][i]]; 41 //v[trie[u][i]] |= v[trie[fail[u]][i]] spread the dangerous !!! 42 q[t ++] = trie[u][i]; 43 } 44 else 45 trie[u][i] = trie[fail[u]][i]; 46 } 47 } 48 int main () 49 {int m, n; 50 map['A'] = 0;map['T'] = 1;map['C'] = 2;map['G'] = 3; 51 scanf ("%d%d", &m, &n);char s[20]; 52 for (int i = 1; i <= m; i ++) 53 scanf ("%s", s), add (s); 54 build (); 55 ans.s[0][0] = 1; 56 for (int i = 0; i <= cnt; i ++) 57 { 58 if (v[i]) continue; 59 for (int j = 0; j < 4; j ++) 60 if (!v[trie[i][j]]) 61 x.s[i][trie[i][j]] ++; 62 } 63 for (; n; n >>= 1) 64 { 65 if (n & 1) 66 ans = ans * x; 67 x = x * x; 68 }int z (0); 69 for (int i = 0; i <= cnt; i ++) 70 z += ans.s[0][i], z %= p; 71 printf ("%d", z); 72 return 0; 73 return 0; 74 }
每个节点都有一个确定的前驱fail
将fail边反向fail边构成一棵树 可以做ali
ali
1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <iostream> 5 using namespace std; 6 const int N = 501000; 7 int L, v[N], ans[N], b[N], a[N], st[N], ed[N], key[N], next[N], head[N], cnt, a_c, trie[N][26], q[N], graphmr, fa[N], fail[N];char s[N]; 8 typedef pair <int, int> pi; 9 vector <pi> vec[N]; 10 vector <pi>:: iterator it; 11 inline void add (int x, int y) 12 { 13 key[graphmr] = y; 14 next[graphmr] = head[x]; 15 head[x] = graphmr ++; 16 } 17 inline void DFS (int x) 18 { 19 a[++ a_c] = x;st[x] = a_c; 20 for (int i = head[x]; ~ i; i = next[i]) 21 DFS (key[i]); 22 a[++ a_c] = x;ed[x] = a_c; 23 } 24 inline void build (char * s) 25 { 26 memset (head, -1, sizeof head); 27 int p = 0, line = 0; 28 for (int i = 0; i <= L; i ++) 29 { 30 if (s[i] >= 'a' && s[i] <= 'z') 31 trie[p][s[i] - 'a'] = ++ cnt, fa[cnt] = p, p = cnt; 32 if (s[i] == 'P') 33 { 34 ++ line; 35 v[line] = p; 36 } 37 if (s[i] == 'B') 38 p = fa[p]; 39 } 40 int h = 1, t = 2; 41 while (h < t) 42 { 43 int u = q[h ++]; 44 for (int i = 0; i < 26; i ++) 45 if (trie[u][i]) 46 { 47 if (u) 48 fail[trie[u][i]] = trie[fail[u]][i], add (trie[fail[u]][i], trie[u][i]); 49 else 50 add (u, trie[u][i]); 51 q[t ++] = trie[u][i]; 52 } 53 else 54 trie[u][i] = trie[fail[u]][i]; 55 } 56 DFS (0); 57 } 58 inline void updata (int x, int r) 59 { 60 for (; x <= 2 * L; x += x & -x) 61 b[x] += r; 62 } 63 inline int query (int x) 64 { 65 int z (0); 66 for (; x; x -= x & -x) 67 z += b[x]; 68 return z; 69 } 70 inline void sol (char * s) 71 { 72 int line = 0, p = 0; 73 for (int i = 0; i < L; i ++) 74 { 75 if (s[i] >= 'a' && s[i] <= 'z') 76 p = trie[p][s[i] - 'a'], updata (st[p], 1); 77 if (s[i] == 'P') 78 { 79 ++ line; 80 for (it = vec[line].begin (); it != vec[line].end (); it ++) 81 ans[it->second] = query (ed[v[it->first]]) - query (st[v[it->first]] - 1); 82 } 83 if (s[i] == 'B') 84 updata (st[p], -1), p = fa[p]; 85 } 86 } 87 int main () 88 { 89 scanf ("%s", s);L = strlen (s); 90 build (s);int n; 91 scanf ("%d", &n); 92 for (int i = 1, x, y; i <= n; i ++) 93 scanf ("%d%d", &x, &y), vec[y].push_back (pi (x, i)); 94 //for (int i = 1; i <= a_c; i ++) 95 // printf ("%d ", a[i]);puts (""); 96 sol (s); 97 for (int i = 1; i <= n; i ++) 98 printf ("%d\n", ans[i]); 99 return 0; 100 }