毒瘤题
先对于模板串建立AC自动机,然后用矩阵$A_{i,j}$是否为$1$表示节点$i$是否能到达节点$j$,在$trie$图建立之后就可以生成这个了
然后线段树维护区间矩阵连乘积
时间复杂度:$O(\text{可过})$
1 %:pragma GCC optimize(2) 2 %:pragma GCC optimize(3) 3 %:pragma GCC optimize("Ofast") 4 %:pragma GCC optimize("inline") 5 %:pragma GCC optimize("-fgcse") 6 %:pragma GCC optimize("-fgcse-lm") 7 %:pragma GCC optimize("-fipa-sra") 8 %:pragma GCC optimize("-ftree-pre") 9 %:pragma GCC optimize("-ftree-vrp") 10 %:pragma GCC optimize("-fpeephole2") 11 %:pragma GCC optimize("-ffast-math") 12 %:pragma GCC optimize("-fsched-spec") 13 %:pragma GCC optimize("unroll-loops") 14 %:pragma GCC optimize("-falign-jumps") 15 %:pragma GCC optimize("-falign-loops") 16 %:pragma GCC optimize("-falign-labels") 17 %:pragma GCC optimize("-fdevirtualize") 18 %:pragma GCC optimize("-fcaller-saves") 19 %:pragma GCC optimize("-fcrossjumping") 20 %:pragma GCC optimize("-fthread-jumps") 21 %:pragma GCC optimize("-funroll-loops") 22 %:pragma GCC optimize("-fwhole-program") 23 %:pragma GCC optimize("-freorder-blocks") 24 %:pragma GCC optimize("-fschedule-insns") 25 %:pragma GCC optimize("inline-functions") 26 %:pragma GCC optimize("-ftree-tail-merge") 27 %:pragma GCC optimize("-fschedule-insns2") 28 %:pragma GCC optimize("-fstrict-aliasing") 29 %:pragma GCC optimize("-fstrict-overflow") 30 %:pragma GCC optimize("-falign-functions") 31 %:pragma GCC optimize("-fcse-skip-blocks") 32 %:pragma GCC optimize("-fcse-follow-jumps") 33 %:pragma GCC optimize("-fsched-interblock") 34 %:pragma GCC optimize("-fpartial-inlining") 35 %:pragma GCC optimize("no-stack-protector") 36 %:pragma GCC optimize("-freorder-functions") 37 %:pragma GCC optimize("-findirect-inlining") 38 %:pragma GCC optimize("-fhoist-adjacent-loads") 39 %:pragma GCC optimize("-frerun-cse-after-loop") 40 %:pragma GCC optimize("inline-small-functions") 41 %:pragma GCC optimize("-finline-small-functions") 42 %:pragma GCC optimize("-ftree-switch-conversion") 43 %:pragma GCC optimize("-foptimize-sibling-calls") 44 %:pragma GCC optimize("-fexpensive-optimizations") 45 %:pragma GCC optimize("-funsafe-loop-optimizations") 46 %:pragma GCC optimize("inline-functions-called-once") 47 %:pragma GCC optimize("-fdelete-null-pointer-checks") 48 49 #include <bits/stdc++.h> 50 using namespace std; 51 typedef long long ll; 52 const int N = 30000 + 10, mod = 998244353; 53 int n, m, q, len, a[N]; 54 char s[N]; 55 56 struct Mat { 57 int a[22][22]; 58 Mat() { for(int i = 0 ; i < len ; ++ i) for(int j = 0 ; j < len ; ++ j) a[i][j] = 0; } 59 int* operator [] (int x) { return a[x]; } 60 Mat operator * (Mat b) { 61 Mat c; 62 for(int i = 0 ; i < len ; ++ i) 63 for(int k = 0 ; k < len ; ++ k) 64 if(a[i][k]) 65 for(int j = 0 ; j < len ; ++ j) 66 c[i][j] = (c[i][j] + 1ll * a[i][k] * b[k][j]) % mod; 67 // for(int i = 0 ; i < len ; ++ i) 68 // for(int j = 0 ; j < len ; ++ j) 69 // for(int k = 0 ; k < len ; ++ k) 70 // c[i][j] = (c[i][j] + 1ll * a[i][k] * b[k][j]) % mod; 71 return c; 72 } 73 } mat[N * 4], m0, m1, m01, init; 74 75 #define lc (id << 1) 76 #define rc (id << 1 | 1) 77 78 void build(int id, int l, int r) { 79 int mid = (l + r) >> 1; 80 if(l == r) { 81 if(a[l] == -1) { 82 mat[id] = m01; 83 } else if(a[l] == 0) { 84 mat[id] = m0; 85 } else if(a[l] == 1) { 86 mat[id] = m1; 87 } 88 } else { 89 build(lc, l, mid), build(rc, mid + 1, r); 90 mat[id] = mat[lc] * mat[rc]; 91 } 92 } 93 94 void modify(int id, int l, int r, int pos, int val) { 95 int mid = (l + r) >> 1; 96 if(l == r) { 97 if(val == -1) { 98 mat[id] = m01; 99 } else if(val == 0) { 100 mat[id] = m0; 101 } else if(val == 1) { 102 mat[id] = m1; 103 } 104 } else if(pos <= mid) modify(lc, l, mid, pos, val), mat[id] = mat[lc] * mat[rc]; 105 else modify(rc, mid + 1, r, pos, val), mat[id] = mat[lc] * mat[rc]; 106 } 107 108 Mat query(int id, int l, int r, int ql, int qr) { 109 int mid = (l + r) >> 1; 110 if(ql <= l && r <= qr) return mat[id]; 111 else if(qr <= mid) return query(lc, l, mid, ql, qr); 112 else if(ql >= mid + 1) return query(rc, mid + 1, r, ql, qr); 113 else return query(lc, l, mid, ql, mid) * query(rc, mid + 1, r, mid + 1, qr); 114 } 115 116 namespace ACM { 117 118 int cnt, nxt[N][2], fail[N], tot[N]; 119 char s[N]; 120 121 void ins() { 122 scanf("%s", s); 123 int x = 0; 124 for(int i = 0 ; s[i] ; ++ i) { 125 int c = s[i] - '0'; 126 if(!nxt[x][c]) nxt[x][c] = ++ cnt; 127 x = nxt[x][c]; 128 } 129 ++ tot[x]; 130 } 131 132 void bfs() { 133 queue<int> q; 134 for(int i = 0 ; i < 2 ; ++ i) { 135 if(nxt[0][i]) { 136 fail[nxt[0][i]] = 0; 137 q.push(nxt[0][i]); 138 } 139 } 140 while(q.size()) { 141 int u = q.front(); q.pop(); 142 for(int i = 0 ; i < 2 ; ++ i) { 143 int v = nxt[u][i]; 144 if(!v) nxt[u][i] = nxt[fail[u]][i]; 145 else { 146 fail[v] = nxt[fail[u]][i]; 147 tot[v] |= tot[fail[v]]; 148 q.push(v); 149 } 150 } 151 } 152 } 153 154 void build() { 155 bfs(); 156 len = cnt + 1; 157 for(int i = 0 ; i < len ; ++ i) { 158 if(tot[i]) continue; 159 m0[i][nxt[i][0]] = 1; 160 m1[i][nxt[i][1]] = 1; 161 162 163 // m01[i][nxt[i][0]] = m01[i][nxt[i][1]] = 1; 164 ++ m01[i][nxt[i][0]]; 165 ++ m01[i][nxt[i][1]]; 166 167 // assert(nxt[i][0] != nxt[i][1]); // ???????????????????? 168 } 169 init[0][0] = 1; 170 } 171 }; 172 173 int ff_query(int l, int r) { 174 long long res = 0; 175 Mat mat = init * query(1, 1, n, l, r); 176 for(int i = 0 ; i < len ; ++ i) 177 if(ACM :: tot[i] == 0) 178 res += mat[0][i]; 179 return res % mod; 180 } 181 char op[10]; 182 int main() { 183 freopen("kill.in", "r", stdin); 184 freopen("kill.out", "w", stdout); 185 scanf("%d%d%d", &n, &m, &q); 186 for(int i = 1 ; i <= n ; ++ i) scanf("%d", &a[i]); 187 for(int i = 1 ; i <= m ; ++ i) ACM :: ins(); ACM :: build(); 188 build(1, 1, n); 189 for(int i = 1, x, y ; i <= q ; ++ i) { 190 scanf("%s%d%d", op, &x, &y); 191 if(op[0] == 'Q') { 192 printf("%d\n", ff_query(x, y)); 193 } else { 194 modify(1, 1, n, x, y); 195 } 196 } 197 }