AC自动机
模板题 hdu2222:
查询主串中出现过几种模式串。
1 #include <bits/stdc++.h> 2 #define rep(i, a, b) for (int i = a; i <= b; i++) 3 #define REP(i, a, b) for (int i = a; i < b; i++) 4 #define drep(i, a, b) for (int i = a; i >= b; i--) 5 #define pb push_back 6 #define mp make_pair 7 #define clr(x) memset(x, 0, sizeof(x)) 8 #define travel(x) for (int i = G[x]; i; i = e[i].nx) 9 #define xx first 10 #define yy second 11 12 using namespace std; 13 14 typedef long long i64; 15 typedef pair<int, int> pii; 16 17 const int inf = ~0U >> 1; 18 const i64 INF = ~0ULL >> 1; 19 //*************************** 20 21 const int maxn = 100005; 22 23 int fail[maxn], ndtot, tab[maxn]; 24 int ch[maxn][128]; 25 char s[10005]; 26 27 void add(char *str, int ha) { 28 int p = 0; 29 for (int i = 0; str[i]; i++) { 30 if (!ch[p][str[i] - 32]) ch[p][str[i] - 32] = ++ndtot; 31 p = ch[p][str[i] - 32]; 32 } 33 tab[p] = ha; 34 } 35 36 int que[maxn]; 37 38 void build() { 39 int qh(0), qt(0); 40 que[++qt] = 0; 41 while (qh != qt) { 42 int x = que[++qh]; 43 REP(i, 0, 128) { 44 if (ch[x][i]) { 45 que[++qt] = ch[x][i]; 46 fail[ch[x][i]] = x ? ch[fail[x]][i] : 0; 47 } 48 else ch[x][i] = ch[fail[x]][i]; 49 } 50 } 51 } 52 53 bool vis[505]; 54 55 int tot = 0, n; 56 void query(char *str, int haha) { 57 bool flag = false; 58 clr(vis); 59 int p = 0; 60 for (int i = 0; str[i]; i++) { 61 p = ch[p][str[i] - 32]; 62 int k = p; 63 while (k) { 64 if (tab[k]) vis[tab[k]] = 1, flag = 1; 65 k = fail[k]; 66 } 67 } 68 if (flag) { 69 printf("web %d:", haha); 70 rep(i, 1, n) if (vis[i]) printf(" %d", i); 71 tot++; 72 puts(""); 73 } 74 } 75 76 int main() { 77 scanf("%d", &n); 78 rep(i, 1, n) { scanf("%s", s); add(s, i); } 79 build(); 80 int m; 81 scanf("%d", &m); 82 tot = 0; 83 rep(i, 1, m) { 84 scanf("%s", s); 85 query(s, i); 86 } 87 printf("total: %d\n", tot); 88 return 0; 89 }
同类题 hdu2896:
也是查询主串中出现过几种模式串。
1 #include <bits/stdc++.h> 2 #define rep(i, a, b) for (int i = a; i <= b; i++) 3 #define REP(i, a, b) for (int i = a; i < b; i++) 4 #define drep(i, a, b) for (int i = a; i >= b; i--) 5 #define pb push_back 6 #define mp make_pair 7 #define clr(x) memset(x, 0, sizeof(x)) 8 #define travel(x) for (int i = G[x]; i; i = e[i].nx) 9 #define xx first 10 #define yy second 11 12 using namespace std; 13 14 typedef long long i64; 15 typedef pair<int, int> pii; 16 17 const int inf = ~0U >> 1; 18 const i64 INF = ~0ULL >> 1; 19 //*************************** 20 21 const int maxn = 100005; 22 23 int fail[maxn], ndtot, tab[maxn]; 24 int ch[maxn][128]; 25 char s[10005]; 26 27 void add(char *str, int ha) { 28 int p = 0; 29 for (int i = 0; str[i]; i++) { 30 if (!ch[p][str[i] - 32]) ch[p][str[i] - 32] = ++ndtot; 31 p = ch[p][str[i] - 32]; 32 } 33 tab[p] = ha; 34 } 35 36 int que[maxn]; 37 38 void build() { 39 int qh(0), qt(0); 40 que[++qt] = 0; 41 while (qh != qt) { 42 int x = que[++qh]; 43 REP(i, 0, 128) { 44 if (ch[x][i]) { 45 que[++qt] = ch[x][i]; 46 fail[ch[x][i]] = x ? ch[fail[x]][i] : 0; 47 } 48 else ch[x][i] = ch[fail[x]][i]; 49 } 50 } 51 } 52 53 bool vis[505]; 54 55 int tot = 0, n; 56 void query(char *str, int haha) { 57 bool flag = false; 58 clr(vis); 59 int p = 0; 60 for (int i = 0; str[i]; i++) { 61 p = ch[p][str[i] - 32]; 62 int k = p; 63 while (k) { 64 if (tab[k]) vis[tab[k]] = 1, flag = 1; 65 k = fail[k]; 66 } 67 } 68 if (flag) { 69 printf("web %d:", haha); 70 rep(i, 1, n) if (vis[i]) printf(" %d", i); 71 tot++; 72 puts(""); 73 } 74 } 75 76 int main() { 77 scanf("%d", &n); 78 rep(i, 1, n) { scanf("%s", s); add(s, i); } 79 build(); 80 int m; 81 scanf("%d", &m); 82 tot = 0; 83 rep(i, 1, m) { 84 scanf("%s", s); 85 query(s, i); 86 } 87 printf("total: %d\n", tot); 88 return 0; 89 }
有一个需要注意的地方,这个题没有多组数据,然后如果写的是数组版,你对存储trie树的数组memset一遍就会mle,可能是如果不memset可以被编译器优化吧。。