AC自动机部分题目
模板题:
Keywords Search
View Code
//#pragma comment(linker,"/STACK:327680000,327680000") #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n) for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i)) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define Read() freopen("data.in", "r", stdin) #define Write() freopen("data.out", "w", stdout); typedef long long LL; const double eps = 1e-8; const double pi = acos(-1.0); const double inf = ~0u>>2; using namespace std; const int N = 10010; struct Node { Node* fail; Node* next[26]; int cnt; Node() { CL(next, NULL); fail = NULL; cnt = 0; } }; class AC_automaton : public Node { public: Node* root; int head, tail; void init() {root = new Node(); head = tail = 0;} void Insert(char* ); void Build(); int Search(char* ); }AC; void AC_automaton::Insert(char* st) { Node* p = root; while(*st) { if(p->next[*st - 'a'] == NULL) { p->next[*st - 'a'] = new Node(); } p = p->next[*st - 'a']; st++; } p->cnt++; } void AC_automaton::Build() { root->fail = NULL; deque<Node* > q; q.push_back(root); while(!q.empty()) { Node* tmp = q.front(); Node* p = NULL; q.pop_front(); for(int i = 0; i < 26; ++i) { if(tmp->next[i] != NULL) { if(tmp == root) tmp->next[i]->fail = root; else { p = tmp->fail; while(p != NULL) { if(p->next[i] != NULL) { tmp->next[i]->fail = p->next[i]; break; } p = p->fail; } if(p == NULL) tmp->next[i]->fail = root; } q.push_back(tmp->next[i]); } } } } int AC_automaton::Search(char* st) { int res = 0, t; Node* p = root; while(*st) { t = *st - 'a'; while(p->next[t] == NULL && p != root) {p = p->fail;} p = (p->next[t] != NULL) ? p->next[t] : root; Node* tmp = p; while(tmp != root && tmp->cnt != -1) { res += tmp->cnt; tmp->cnt = -1; tmp = tmp->fail; } st++; } return res; } char ss[1000010]; int main() { //Read(); int T, n; scanf("%d", &T); while(T--) { AC.init(); scanf("%d", &n); while(n--) {scanf("%s", ss); AC.Insert(ss);} AC.Build(); scanf("%s", ss); printf("%d\n", AC.Search(ss)); } return 0; }
病毒侵袭
View Code
//#pragma comment(linker,"/STACK:327680000,327680000") #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n) for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i)) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define Read() freopen("data.in", "r", stdin) #define Write() freopen("data.out", "w", stdout); typedef long long LL; const double eps = 1e-8; const double pi = acos(-1.0); const double inf = ~0u>>2; using namespace std; const int N = 10010; struct Node { Node* fail; Node* next[130]; int cnt; Node() { CL(next, NULL); fail = NULL; cnt = 0; } }; int ans[N], tt; bool vis[N]; class AC_automaton : public Node { public: Node* root; int head, tail; void init() {root = new Node(); head = tail = 0;} void Insert(char*, int ); void Build(); int Search(char* ); }AC; void AC_automaton::Insert(char* st, int num) { Node* p = root; while(*st) { int t = *st; if(p->next[t] == NULL) { p->next[t] = new Node(); } p = p->next[t]; st++; } p->cnt = num; } void AC_automaton::Build() { root->fail = NULL; deque<Node* > q; q.push_back(root); while(!q.empty()) { Node* tmp = q.front(); Node* p = NULL; q.pop_front(); for(int i = 0; i < 130; ++i) { if(tmp->next[i] != NULL) { if(tmp == root) tmp->next[i]->fail = root; else { p = tmp->fail; while(p != NULL) { if(p->next[i] != NULL) { tmp->next[i]->fail = p->next[i]; break; } p = p->fail; } if(p == NULL) tmp->next[i]->fail = root; } q.push_back(tmp->next[i]); } } } } int AC_automaton::Search(char* st) { int res = 0, t; Node* p = root; while(*st) { t = *st; while(p->next[t] == NULL && p != root) {p = p->fail;} p = (p->next[t] != NULL) ? p->next[t] : root; Node* tmp = p; while(tmp != root && tmp->cnt) { ans[tt++] = tmp->cnt; // vis[tmp->cnt] = true; tmp = tmp->fail; } st++; } return res; } char ss[10010]; int main() { //Read(); int N, M, i, j; int tol; while(~scanf("%d", &N)) { AC.init(); for(i = 1; i <= N; ++i) { scanf("%s", ss); AC.Insert(ss, i); } AC.Build(); tol = 0; scanf("%d", &M); for(i = 1; i <= M; ++i) { scanf("%s", ss); //CL(vis, false); tt = 0; AC.Search(ss); if(tt == 0) continue; sort(ans, ans + tt); printf("web %d:", i); for(j = 0; j < tt; ++j) { printf(" %d", ans[j]); } puts(""); tol++; } printf("total: %d\n", tol); } return 0; }
病毒侵袭持续中
View Code
//#pragma comment(linker,"/STACK:327680000,327680000") #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n) for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i)) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define Read() freopen("data.in", "r", stdin) #define Write() freopen("data.out", "w", stdout); typedef long long LL; const double eps = 1e-8; const double pi = acos(-1.0); const double inf = ~0u>>2; using namespace std; const int maxn = 1024; struct Node { Node* fail; Node* next[26]; int cnt; Node() { CL(next, NULL); fail = NULL; cnt = 0; } }; int ans[maxn]; class AC_automaton : public Node { public: Node* root; void init() {root = new Node();} void Insert(char*, int ); void Build(); int Search(char* ); void DEL(Node* p) { for(int i = 0; i < 26; ++i) if(p->next[i] != NULL) DEL(p->next[i]); delete p; } void Clear() { DEL(root); } }AC; void AC_automaton::Insert(char* st, int num) { Node* p = root; while(*st) { int t = *st - 'A'; if(p->next[t] == NULL) { p->next[t] = new Node(); } p = p->next[t]; st++; } p->cnt = num; } void AC_automaton::Build() { root->fail = NULL; deque<Node* > q; q.push_back(root); while(!q.empty()) { Node* tmp = q.front(); Node* p = NULL; q.pop_front(); for(int i = 0; i < 26; ++i) { if(tmp->next[i] != NULL) { if(tmp == root) tmp->next[i]->fail = root; else { p = tmp->fail; while(p != NULL) { if(p->next[i] != NULL) { tmp->next[i]->fail = p->next[i]; break; } p = p->fail; } if(p == NULL) tmp->next[i]->fail = root; } q.push_back(tmp->next[i]); } } } } int AC_automaton::Search(char* st) { int res = 0, t; Node* p = root; while(*st) { if(!(*st >= 'A' && *st <= 'Z')) {++st; p = root; continue ;} t = *st - 'A'; while(p->next[t] == NULL && p != root) {p = p->fail;} p = (p->next[t] != NULL) ? p->next[t] : root; Node* tmp = p; while(tmp != root && tmp->cnt) { ans[tmp->cnt]++; tmp = tmp->fail; } st++; } return res; } char tmp[1100][55]; char ss[2000010]; int main() { //Read(); int n, i; while(~scanf("%d\n", &n)) { AC.init(); for(i = 1; i <= n; ++i) { gets(tmp[i]); AC.Insert(tmp[i], i); } AC.Build(); gets(ss); CL(ans, 0); AC.Search(ss); for(i = 1; i <= n; ++i) { if(ans[i]) { printf("%s: %d\n", tmp[i], ans[i]); } } AC.Clear(); } return 0; }
AC自动机+矩阵
DNA Sequence
问你长度为N的串中不包含了模式串的串有几个
较为详细的讲解:http://hi.baidu.com/ccsu_010/item/7847a3c17f6fe2bc0d0a7b89
View Code
//#pragma comment(linker,"/STACK:327680000,327680000") #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n) for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i)) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define Read() freopen("data.in", "r", stdin) #define Write() freopen("data.out", "w", stdout); typedef long long LL; const double eps = 1e-8; const double pi = acos(-1.0); const double inf = ~0u>>2; using namespace std; const int MOD = 100000; struct Node { int fail; int next[4]; bool end; void Init() { CL(next, -1); fail = -1; end = 0; } }; Node node[110]; int q[110]; int node_num; int get(char c) { switch (c) { case 'A' : return 0; case 'G' : return 1; case 'C' : return 2; case 'T' : return 3; default : return -1; } } class AC_automaton { public: int head, tail; void Init() { for(int i = 0; i < 110; ++i) node[i].Init(); node_num = 1; head = tail = 0; } void Insert(char* st) { int t, p = 0; for( ; *st; ++st) { if(node[p].end) break; t = get(*st); if(node[p].next[t] == -1) { node[p].next[t] = node_num++; } p = node[p].next[t]; } node[p].end = true; } void Build() { q[tail++] = 0; while(head < tail) { int tmp = q[head++]; int p; for(int i = 0; i < 4; ++i) { if(node[tmp].next[i] != -1) { if(tmp == 0) node[node[tmp].next[i]].fail = 0; else { p = node[tmp].fail; while(p != -1) { if(node[p].next[i] != -1) { node[node[tmp].next[i]].fail = node[p].next[i]; if(node[node[p].next[i]].end) node[node[tmp].next[i]].end = 1; break; } p = node[p].fail; } if(p == -1) node[node[tmp].next[i]].fail = 0; } q[tail++] = node[tmp].next[i]; } } } } }AC; char ss[15]; struct Mat { LL mat[110][110]; }g; Mat operator * (Mat a, Mat b) { Mat c; memset(c.mat, 0, sizeof(c.mat)); int i, j, k; for(k = 0; k < node_num; ++k) { for(i = 0; i < node_num; ++i) { if(a.mat[i][k] <= 0) continue; for(j = 0; j < node_num; ++j) { if(b.mat[k][j] <= 0) continue; //剪枝 c.mat[i][j] += a.mat[i][k] * b.mat[k][j]; if(c.mat[i][j] >= MOD) c.mat[i][j] %= MOD; } } } return c; } Mat operator ^ (Mat a, int k) { Mat c; int i, j; for(i = 0; i < node_num; ++i) for(j = 0; j < node_num; ++j) c.mat[i][j] = (i == j); //初始化为单位矩阵 for(; k; k >>= 1) { if(k&1) c = c*a; a = a*a; } return c; } void Build_Matrix() { CL(g.mat, 0); int i, j; for(i = 0; i < node_num; ++i) { if(node[i].end) continue; for(j = 0; j < 4; ++j) { if(node[i].next[j] != -1 && node[node[i].next[j]].end == 0) g.mat[i][node[i].next[j]]++; //goto line105 else if(node[i].next[j] == -1) { if(i == 0) {g.mat[i][i]++; continue;} int tmp = i; while(node[tmp].next[j] == -1) { tmp = node[tmp].fail; if(tmp == 0) break; } if(node[tmp].next[j] != -1 && node[node[tmp].next[j]].end == 0) g.mat[i][node[tmp].next[j]]++; else if(node[tmp].next[j] == -1 && tmp == 0) g.mat[i][0]++; } } } } LL solve(int n) { Build_Matrix(); /* for(int i = 0; i < node_num; ++i) { for(int j = 0; j < node_num; ++j) { printf("%lld ", g.mat[i][j]); } puts(""); } */ g = g^n; LL ans = 0; for(int i = 0; i < node_num; ++i) { if(node[i].end != 0) continue; ans = ans + g.mat[0][i]; if(ans >= MOD) ans %= MOD; } return ans; } int main() { //Read(); //Write(); int n, m, i; while(~scanf("%d%d", &m, &n)) { AC.Init(); for(i = 0; i < m; ++i) { scanf("%s", ss); AC.Insert(ss); } AC.Build(); printf("%lld\n", solve(n)); } return 0; }
AC自动机+DP
DNA REPAIR
给定n个疾病DNA序列,和一个待修复序列str。用最小的次数修改待修复序列,使其不含疾病DNA序列。
dp[i][j]表示跑到母串第i位置,自动机上j状态时最小改变的字符数;
dp[i+1][tmp] = min(dp[i+1][tmp], dp[i][j] + (st[i] ==k)); k表示从j状态到达tmp状态所走的边(注意区分dp的状态和自动机的状态)
View Code
//#pragma comment(linker,"/STACK:327680000,327680000") #include <iostream> #include <cstdio> #include <cmath> #include <vector> #include <cstring> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define REP(i, n) for((i) = 0; (i) < (n); ++(i)) #define FOR(i, l, h) for((i) = (l); (i) <= (h); ++(i)) #define FORD(i, h, l) for((i) = (h); (i) >= (l); --(i)) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d\n", x) #define Read() freopen("data.in", "r", stdin) #define Write() freopen("data.out", "w", stdout); typedef long long LL; const double eps = 1e-8; const double pi = acos(-1.0); const int inf = ~0u>>2; using namespace std; const int maxn = 1024; struct Node { int fail; int next[4]; int cnt; bool end; void init() { fail = -1; cnt = 0; CL(next, -1); end = false; } }; Node node[maxn]; int node_num; int dp[maxn][maxn]; int q[maxn]; int get(char c) { switch(c) { case 'A' : return 0; case 'T' : return 1; case 'G' : return 2; case 'C' : return 3; default : return -1; } } class AC_automaton { public: int head, tail; void init() { for(int i = 0; i < maxn; ++i) node[i].init(); head = tail = 0; node_num = 1; } void Insert(char* st) { int p = 0, t; for( ; *st; ++st) { t = get(*st); if(node[p].end) break; if(node[p].next[t] == -1) { node[p].next[t] = node_num++; } p = node[p].next[t]; } node[p].end = true; } void Build() { int tmp, p, i; q[tail++] = 0; while(head < tail) { tmp = q[head++]; for(i = 0; i < 4; ++i) { if(node[tmp].next[i] == -1) continue; if(tmp == 0) node[node[tmp].next[i]].fail = 0; else { p = node[tmp].fail; while(p != -1) { if(node[p].next[i] != -1) { node[node[tmp].next[i]].fail = node[p].next[i]; if(node[node[p].next[i]].end) node[node[tmp].next[i]].end = true; break; } p = node[p].fail; } if(p == -1) node[node[tmp].next[i]].fail = 0; } q[tail++] = node[tmp].next[i]; } } } int search(char* st) { int res = 0, t; int p = 0; for( ; *st; ++st) { t = get(*st); while(node[p].next[t] == -1 && p != 0) p = node[p].fail; p = node[p].next[t]; if(p == -1) p = 0; int tmp = p; while(tmp != 0 && node[tmp].cnt ) { res += node[tmp].cnt; node[tmp].cnt = -1; tmp = node[tmp].fail; } } return res; } }AC; char st[maxn]; int solve() { int i, j, k, tmp, len = strlen(st); for(i = 0; i <= len; ++i) { for(j = 0; j <= node_num; ++j) dp[i][j] = inf; } dp[0][0] = 0; for(i = 0; i < len; ++i) { for(j = 0; j < node_num; ++j) { if(dp[i][j] == inf) continue; for(k = 0; k < 4; ++k) { tmp = j; while(tmp != -1) { if(node[tmp].next[k] != -1) {tmp = node[tmp].next[k]; break;} tmp = node[tmp].fail; } if(tmp == -1) tmp = 0; if(node[tmp].end == false) dp[i+1][tmp] = min(dp[i+1][tmp], dp[i][j] + (get(st[i]) != k)); } } } int ans = inf; for(j = 0; j < node_num; ++j) { ans = min(ans, dp[len][j]); } return ans == inf ? -1 : ans; } int main() { //Read(); int n, i, cas = 0; while(scanf("%d", &n), n) { AC.init(); for(i = 0; i < n; ++i) { scanf("%s", st); AC.Insert(st); } scanf("%s", st); AC.Build(); printf("Case %d: %d\n", ++cas, solve()); } return 0; }