#include #include #include #include #include #include #include #define unlikely(x) __builtin_expect(!!(x), 0) struct char_reader { FILE *f; char *buf, *p1, *p2; int size; char_reader(FILE *fin, int bufsize = 1 << 16) { f = fin; size = bufsize; p1 = p2 = 0; buf = new char[size]; } ~char_reader() { delete[] buf; } inline int operator()() { return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, size, f), p1 == p2) ? EOF : *p1++; } }; struct char_writer { FILE *f; char *buf, *p, *end; int size; char_writer(FILE *fout, int bufsize = 1 << 16) { f = fout; size = bufsize; buf = new char[size]; p = buf; end = buf + bufsize; } ~char_writer() { fwrite(buf, p - buf, 1, f); delete[] buf; } inline char operator()(char ch) { if (unlikely(end == p)) { fwrite(buf, end - buf, 1, f); p = buf; } return *p++ = ch; } }; char_reader gch(stdin); char_writer wch(stdout); template inline int read(T &t) { bool f = false; int ch; while (ch = gch(), !((ch >= '0' && ch <= '9') || ch == '-')) { if (ch == EOF) return 0; } t = 0; if (ch == '-') f = true, ch = gch(); t = ch ^ 48; while (ch = gch(), ch >= '0' && ch <= '9') t = (t << 3) + (t << 1) + (ch ^ 48); if (f) t = -t; return 1; } inline int read(char &c) { c = 0; int ch; while (ch = gch(), (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t')) { if (ch == EOF) return 0; } c = ch; return 1; } inline int read(char *s) { int ch; while (ch = gch(), (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t')) { if (ch == EOF) return 0; } *s++ = ch; while (ch = gch(), !(ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t') && ch != EOF) *s++ = ch; *s++ = 0; return 1; } inline int read(const char *s) { return read((char *)s); } inline int readline(char *s) { int ch; while (ch = gch(), (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t')) { if (ch == EOF) return 0; } *s++ = ch; while (ch = gch(), !(ch == '\n' || ch == '\r') && ch != EOF) *s++ = ch; *s++ = 0; return 1; } inline int readline(const char *s) { return readline((char *)s); } template inline void write(T t) { int stk[20], cnt = 0; if (t == 0) { wch('0'); return; } if (t < 0) { wch('-'); t = -t; } while (t > 0) { stk[cnt++] = t % 10; t /= 10; } while (cnt) wch(stk[--cnt] + '0'); } inline void write(char t) { wch(t); } inline void write(char *s) { while (*s) wch(*s++); } inline void write(const char *s) { write((char *)s); } #if __cplusplus >= 201103L template inline int read(T &t, Args &...args) { return read(t) + read(args...); } template inline void write(T t, Args... args) { write(t); write(args...); } #else template inline int read(A_t &a, B_t &b) { return read(a) + read(b); } template inline int read(A_t &a, B_t &b, C_t &c) { return read(a) + read(b) + read(c); } template inline int read(A_t &a, B_t &b, C_t &c, D_t &d) { return read(a) + read(b) + read(c) + read(d); } template inline void write(A_t a, B_t b) { write(a); write(b); } template inline void write(A_t a, B_t b, C_t c) { write(a); write(b); write(c); } template inline void write(A_t a, B_t b, C_t c, D_t d) { write(a); write(b); write(c); write(d); } #endif using namespace std; typedef long long LL; const int kMaxN = 3e5 + 100; int trans[kMaxN][26], fail[kMaxN], node_cnt = 0; char buf[kMaxN]; char *s[kMaxN]; int n, m; LL raw_opt[kMaxN]; void BuildACAutomaton() { for (int i = 1; i <= n; i++) { char *p = s[i]; int nd = 0; while (*p) { if (trans[nd][*p - 'a'] == 0) trans[nd][*p - 'a'] = ++node_cnt; nd = trans[nd][*p - 'a']; p++; } } int L = 0, R = 0; int *Q = new int[kMaxN](); fail[0] = -1; Q[0] = 0; while (L <= R) { int u = Q[L++]; for (int i = 0; i < 26; i++) { if (trans[u][i] != 0) { int v = fail[u]; while (v != -1 && trans[v][i] == 0) v = fail[v]; // 反复沿着失配边跳转 if (v != -1) fail[trans[u][i]] = trans[v][i]; // 子节点的内容在父节点就处理好 Q[++R] = trans[u][i]; } else if (fail[u] != -1) trans[u][i] = trans[fail[u]][i]; // 其余情况置0,回到初始状态 } } delete[] Q; } struct ValContainer { int son[kMaxN], size[kMaxN], dep[kMaxN]; int nid[kMaxN], dfn[kMaxN], top[kMaxN]; int data[kMaxN]; vector G[kMaxN]; int *fa, n, cnt; void dfs1(int u) { son[u] = -1; size[u] = 1; for (int i = G[u].size() - 1; i >= 0; --i) { int v = G[u][i]; dep[v] = dep[u] + 1; dfs1(v); if (son[u] == -1 || size[v] > size[son[u]]) son[u] = v; } } void dfs2(int u, int tp) { top[u] = tp; cnt++; dfn[u] = cnt; nid[cnt] = u; if (son[u] == -1) return; dfs2(son[u], tp); for (int i = G[u].size() - 1; i >= 0; i--) { int v = G[u][i]; if (v != son[u]) dfs2(v, v); } } void Init(int __n, int *__fa) { fa = __fa; n = __n; for (int i = 0; i <= node_cnt; i++) if (fa[i] != -1) G[fa[i]].push_back(i); dfs1(0); dfs2(0, 0); } inline void __BIT_Modify(int x, int delta) { for (; x <= cnt; x += x & (-x)) data[x] += delta; } inline int __BIT_Query(int x) { int res = 0; for (; x > 0; x -= x & (-x)) res += data[x]; return res; } inline void Modify(int u, int delta) { __BIT_Modify(dfn[u], delta); } LL Query(int u) { LL res = 0; int p = u; do { int T = top[p]; res += __BIT_Query(dfn[p]) - __BIT_Query(dfn[T] - 1); p = fa[T]; } while (p >= 0); return res; } } Val; int main() { #ifdef local freopen("pro.in", "r", stdin); #endif read(n, m); for (int i = 1; i <= n; i++) { read(raw_opt[i], buf); int len = strlen(buf); s[i] = new char[len + 5]; for (int j = 0; j <= len; j++) s[i][j] = buf[j]; } BuildACAutomaton(); Val.Init(n, fail); LL last_ans = 0; for (int i = 1; i <= n; i++) { int opt = (last_ans * m) ^ (LL)raw_opt[i]; if (opt == 1 || opt == 2) { int delta = (opt == 1 ? 1 : -1); int nd = 0; char *p = s[i]; while (*p) nd = trans[nd][(*p++) - 'a']; Val.Modify(nd, delta); } else if (opt == 3) { last_ans = 0; int nd = 0; char *p = s[i]; while (*p) { nd = trans[nd][*p - 'a']; last_ans += Val.Query(nd); p++; } write(last_ans, '\n'); } else throw runtime_error("Unknown opt"); } return 0; }