Files
SH-Quizzes/ACMOJ-1795.cpp
2023-12-23 22:23:48 +08:00

294 lines
6.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <exception>
#include <stdexcept>
#include <vector>
#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 <typename T>
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 <typename T>
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 <typename T, typename... Args>
inline int read(T &t, Args &...args) {
return read(t) + read(args...);
}
template <typename T, typename... Args>
inline void write(T t, Args... args) {
write(t);
write(args...);
}
#else
template <typename A_t, typename B_t>
inline int read(A_t &a, B_t &b) {
return read(a) + read(b);
}
template <typename A_t, typename B_t, typename C_t>
inline int read(A_t &a, B_t &b, C_t &c) {
return read(a) + read(b) + read(c);
}
template <typename A_t, typename B_t, typename C_t, typename D_t>
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 <typename A_t, typename B_t>
inline void write(A_t a, B_t b) {
write(a);
write(b);
}
template <typename A_t, typename B_t, typename C_t>
inline void write(A_t a, B_t b, C_t c) {
write(a);
write(b);
write(c);
}
template <typename A_t, typename B_t, typename C_t, typename D_t>
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<int> 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;
}