由于有插入和删除,普通AC自动机不好解决,建立fail树就好了。。。
#include <iostream> #include <queue> #include <stack> #include <map> #include <set> #include <bitset> #include <cstdio> #include <algorithm> #include <cstring> #include <climits> #include <cstdlib> #include <cmath> #include <time.h> #define maxn 1000005 #define maxm 1000005 #define eps 1e-10 #define mod 1000000007 #define INF 999999999 #define lowbit(x) (x&(-x)) #define mp make_pair #define ls o<<1 #define rs o<<1 | 1 #define lson o<<1, L, mid #define rson o<<1 | 1, mid+1, R #pragma comment(linker, "/STACK:16777216") typedef long long LL; typedef unsigned long long ULL; //typedef int LL; using namespace std; LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;} LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;} void scanf(int &__x){__x=0;char __ch=getchar();while(__ch==' '||__ch=='\n')__ch=getchar();while(__ch>='0'&&__ch<='9')__x=__x*10+__ch-'0',__ch = getchar();} LL gcd(LL _a, LL _b){if(!_b) return _a;else return gcd(_b, _a%_b);} // head int mpp[maxn]; struct AC { int next[maxn][26]; int fail[maxn]; int end[maxn]; char s[maxn]; queue<int> q; int root, now, top; int newnode(void) { end[top] = 0; fail[top] = -1; for(int i = 0; i < 26; i++) next[top][i] = -1; return top++; } void init(void) { top = 0; root = newnode(); } void insert(int x) { scanf("%s", s); int len = strlen(s), t; now = root; for(int i = 0; i < len; i++) { t = s[i] - 'a'; if(next[now][t] == -1) next[now][t] = newnode(); now = next[now][t]; } end[now]++; mpp[x] = now; } void build(void) { now = root; for(int i = 0; i < 26; i++) if(next[now][i] == -1) next[now][i] = root; else { fail[next[now][i]] = root; q.push(next[now][i]); } while(!q.empty()) { now = q.front(), q.pop(); //end[now] += end[fail[now]]; for(int i = 0; i < 26; i++) if(next[now][i] == -1) next[now][i] = next[fail[now]][i]; else { fail[next[now][i]] = next[fail[now]][i]; q.push(next[now][i]); } } } }ac; struct Edge { int v; Edge *next; }pool[maxm], *edges, *H[maxn]; int sum[maxn << 2], delta[maxn << 2]; int in[maxn], out[maxn]; int flag[maxn]; char s[maxn]; int n, m, dfs_clock; void addedges(int u, int v) { edges->v = v; edges->next = H[u]; H[u] = edges++; } void init(void) { dfs_clock = 0; edges = pool; memset(H, 0, sizeof H); memset(flag, 0, sizeof flag); } void read(void) { scanf("%d%d", &m, &n); ac.init(); for(int i = 1; i <= n; i++) ac.insert(i); ac.build(); } void DFS(int u) { in[u] = ++dfs_clock; for(Edge *e = H[u]; e; e = e->next) DFS(e->v); out[u] = dfs_clock; } void pushup(int o) { sum[o] = sum[ls] + sum[rs]; } void pushdown(int o) { if(!delta[o]) return; sum[ls] += delta[o]; sum[rs] += delta[o]; delta[ls] += delta[o]; delta[rs] += delta[o]; delta[o] = 0; } void build(int o, int L, int R) { sum[o] = 0; if(L == R) return; int mid = (L + R) >> 1; build(lson); build(rson); } void updata(int o, int L, int R, int ql, int qr, int v) { if(ql <= L && qr >= R) { sum[o] += v; delta[o] += v; return; } pushdown(o); int mid = (L + R) >> 1; if(ql <= mid) updata(lson, ql, qr, v); if(qr > mid) updata(rson, ql, qr, v); pushup(o); } int query(int o, int L, int R, int q) { if(L == R) return sum[o]; pushdown(o); int mid = (L + R) >> 1; if(q <= mid) return query(lson, q); else return query(rson, q); pushup(o); } void work(void) { for(int i = 1; i < ac.top; i++) addedges(ac.fail[i], i); DFS(ac.root); build(1, 1, ac.top); for(int i = 1; i < ac.top; i++) updata(1, 1, ac.top, in[i], out[i], ac.end[i]); int x; while(m--) { getchar(); char ch = getchar(); if(ch == '+') { scanf("%d", &x); if(flag[x] == 0) continue; updata(1, 1, ac.top, in[mpp[x]], out[mpp[x]], ac.end[mpp[x]]); flag[x] = 0; } else if(ch == '-') { scanf("%d", &x); if(flag[x] == 1) continue; updata(1, 1, ac.top, in[mpp[x]], out[mpp[x]], -ac.end[mpp[x]]); flag[x] = 1; } else { scanf("%s", s); int len = strlen(s); int now = ac.root, ans = 0; for(int i = 0; i < len; i++) { int t = s[i] - 'a'; now = ac.next[now][t]; ans += query(1, 1, ac.top, in[now]); } printf("%d\n", ans); } } } int main(void) { init(); read(); work(); return 0; }