跟2010福州的现场赛那题基本一样的,只是多了个去重。。上半年在金华邀请赛的时候还不会AC自动机,今天突然想起来就找出来写了一下。。数据给的很大,不过空间给的也是巨大=。=
解码后就是裸的自动机,把包含的串标记一下,再用自动机找这些串的子串去重即可。
1 #include <string.h> 2 #include <stdio.h> 3 #define MAXN 3000000 4 int cas, n; 5 int pos, next[MAXN][26], fail[MAXN], id[MAXN], flag[MAXN]; 6 char s[MAXN*2], ss[MAXN*2], sss[2600][1200]; 7 char *trans(char *ss, char *s){ 8 int len = 0, pp = 0; 9 for (int i = 0; s[i]; i++) { 10 if(s[i] == '[' || s[i] == ']')pp = 0; 11 else if(s[i] >= '0' && s[i] <= '9')pp = pp*10+s[i]-'0'; 12 else if(s[i] >= 'A' && s[i] <= 'Z'){ 13 if (pp == 0) ss[len++] = s[i]; 14 else while (pp--) ss[len++] = s[i]; 15 } 16 } 17 ss[len] = '\0'; 18 return ss; 19 } 20 int newnode(){ 21 memset(next[pos], 0, sizeof next[pos]); 22 id[pos] = -1, fail[pos] = flag[pos] = 0; 23 return pos++; 24 } 25 void insert(char *s, int ids){ 26 int p = 0; 27 for (int i = 0; s[i]; i++) { 28 int &x = next[p][s[i] - 'A']; 29 p = x ? x : x = newnode(); 30 } 31 id[p] = ids; 32 } 33 int q[MAXN], front, rear; 34 void makefail(){ 35 q[front = rear = 0] = 0,rear++; 36 while (front < rear) { 37 int u = q[front++]; 38 for (int i = 0; i < 26; i++) { 39 int v = next[u][i]; 40 if (v) q[rear++] = v; 41 else next[u][i] = next[fail[u]][i]; 42 if (v&&u) fail[v] = next[fail[u]][i]; 43 } 44 } 45 } 46 int vis[3000]; 47 void removestr(int ids, char *s){ 48 for (int i = 0, p = 0; s[i]; i++){ 49 p = next[p][s[i]-'A']; 50 for (int j = p; j; j = fail[j]){ 51 if (id[j] >= 0 && ids != id[j]) vis[id[j]] = 0; 52 } 53 } 54 } 55 int makeans(char *s){ 56 memset(vis, 0, sizeof vis); 57 for (int i = 0, p = 0; s[i]; i++){ 58 p = next[p][s[i]-'A']; 59 for (int j = p; j && flag[j] != -1; j = fail[j]){ 60 if (id[j] >= 0) vis[id[j]] = 1; 61 flag[j] = -1; 62 } 63 } 64 for (int i = 0; i < n; i++) if(vis[i] == 1) removestr(i, sss[i]); 65 int ans = 0; 66 for (int i = 0; i < n; i++) if(vis[i] == 1) ans ++; 67 return ans; 68 } 69 int main(){ 70 //freopen("test.in", "r", stdin); 71 scanf("%d", &cas); 72 while (cas--) { 73 scanf("%d", &n); 74 pos = 0; newnode(); 75 for (int i = 0; i < n; i++) { 76 scanf("%s", s); 77 trans(sss[i], s); 78 insert(sss[i], i); 79 } 80 makefail(); 81 scanf("%s", s); 82 trans(ss, s); 83 printf("%d\n", makeans(ss)); 84 } 85 return 0; 86 }