首页 > 代码库 > POJ 4052 AC自动机

POJ 4052 AC自动机

【题意】:

给你n个字符串和一个文本,问有多少个字符串满足如下条件:该字符串包含在文本,该字符串不为其它字符串的子串。

【知识点】:

Ac自动机,处理字符串

【题解】:

集训比赛的时候当时被题目的数据量吓到了,不敢用ac自动机。但在网上看到题解时,然后瞬间就感觉自己想多了。。。

很水的一道ac自动机处理字符串的题目,先将查询的字符做成字典树,然后在文本中查找字符串是否存在。

在处理去子串上,我的做法是查找文本时去除后缀相同的包含子串。然后单独在搜索剩余可用字符串前缀相同子串。

【代码】:

  1 #include <map>  2 #include <set>  3 #include <cmath>  4 #include <ctime>  5 #include <queue>  6 #include <stack>  7 #include <cstdio>  8 #include <string>  9 #include <vector> 10 #include <cstring> 11 #include <sstream> 12 #include <iostream> 13 #include <algorithm> 14 #include <bitset> 15 #include <climits> 16 using namespace std; 17  18 #define wh while 19 #define inf (int)(~0u/2) 20 #define FOR(i, n) for(int i = 0; i < n; i++) 21 #define FOR1(i, n) for(int i = 1; i < n; i++) 22 #define FOR2(i, n) for(int i = 0; i <= n; i++) 23 #define REP(i,n) for(int i = 1; i <= n; i++) 24 #define FORI(it,n) for(typeof(n.begin()) it = n.begin(); it != n.end(); it++) 25 #define sf scanf 26 #define pf printf 27 #define frs first 28 #define sec second 29 #define psh push_back 30 #define mkp make_pair 31 #define PB(x) push_back(x) 32 #define MP(x, y) make_pair(x, y) 33 #define clr(abc,z) memset(abc,z,sizeof(abc)) 34 #define lt(v) v << 1 35 #define rt(v) v << 1 | 1 36 #define mid ((l + r) >> 1) 37 #define lson l, mid, v << 1 38 #define rson mid + 1, r, v << 1 | 1 39  40 #define fre freopen("1.txt", "r", stdin) 41  42 typedef long long LL; 43 typedef long double LD; 44  45 const int maxn = 3000; 46 const int maxlen = 1300; 47 const int maxlen2 = 3e6 + 10; 48 char st[maxn][maxlen]; 49 char ctmp[maxlen2 * 2]; 50 char text[maxlen2 * 2]; 51 bool vis[maxn]; 52  53 const int SIGMA_SIZE = 26; 54 const int MAXNODE = 3e6 + 10; 55 const int MAXS = 150 + 10; 56  57 char* deal(char* res, char* s){ 58     int len = 0; int t = 0; 59     for(int i = 0; s[i]; i++){ 60         if(s[i] == [ || s[i] == ]) t = 0; 61         else if(s[i] >= 0 && s[i] <= 9) t = t * 10 + s[i] - 0; 62         else if(s[i] >= A && s[i] <= Z){ 63             if(t == 0) 64                 res[len++] = s[i]; 65             else{ 66                 while(t--) 67                     res[len++] = s[i]; 68             } 69         } 70     } 71     res[len] = \0; 72     return res; 73 } 74 struct AhoCorasickAutomata { 75     int ch[MAXNODE][SIGMA_SIZE]; 76     int f[MAXNODE]; 77     int val[MAXNODE]; 78     int last[MAXNODE]; 79     int sz; 80     void init() { 81         sz = 1; 82         memset(ch[0], 0, sizeof(ch[0])); 83     } 84     int idx(char c) { 85         return c - A; 86     } 87     void _insert(char *s, int v) { 88         int u = 0, n = strlen(s); 89         for(int i = 0; i < n; i++) { 90             int c = idx(s[i]); 91             if(!ch[u][c]) { 92                 memset(ch[sz], 0, sizeof(ch[sz])); 93                 val[sz] = 0; 94                 ch[u][c] = sz++; 95             } 96             u = ch[u][c]; 97         } 98         val[u] = v; 99     }100     void doA(int j) {101         if(j) {102             vis[val[j]] = true;103         }104     }105     void doB(int j) {106         if(j) {107             vis[val[j]] = false;108             doB(last[j]);109         }110     }111     void _find(char* T) {112         int n = strlen(T);113         int j = 0;114         for(int i = 0; i < n; i++) {115             int c = idx(T[i]);116             while(j && !ch[j][c]) j = f[j];117             j = ch[j][c];118             if(val[j])119                 doA(j);120             if(val[last[j]])121                 doB(last[j]);122         }123     }124     void getFail() {125         queue<int> q;126         f[0] = 0;127         for(int c = 0; c < SIGMA_SIZE; c++) {128             int u = ch[0][c];129             if(u) {130                 f[u] = 0;131                 q.push(u);132                 last[u] = 0;133             }134         }135         while(!q.empty()) {136             int r = q.front();137             q.pop();138             for(int c = 0; c < SIGMA_SIZE; c++) {139                 int u = ch[r][c];140                 if(!u) continue;141                 q.push(u);142                 int v = f[r];143                 while(v && !ch[v][c]) v = f[v];144                 f[u] = ch[v][c];145                 last[u] = val[f[u]] ? f[u] : last[f[u]];146             }147         }148     }149     void delout(char* tmp){150         int u = 0, n = strlen(tmp);151         for(int i = 0; i < n - 1; i++) {152             int c = idx(tmp[i]);153             u = ch[u][c];154             if(val[u])155                 vis[val[u]] = false;156         }157     }158 };159 160 AhoCorasickAutomata ac;161 int main() {162     int T; sf("%d", &T);163     REP(cas, T){164         clr(vis, 0);165         ac.init(); int n; sf("%d", &n);166         REP(i, n){167             sf("%s", ctmp);168             deal(st[i], ctmp);169             ac._insert(st[i], i);170         }171         ac.getFail();172         sf("%s", ctmp); deal(text, ctmp);173         ac._find(text); int cnt = 0;174         REP(i, n){175             if(vis[i])176                 ac.delout(st[i]);177         }178         REP(i, n){179             if(vis[i]){180                 cnt++;181             }182         }183         pf("%d\n", cnt);184     }185     return 0;186 }
View Code