题意:
给你一个串S以及一个字符串数组T[1..m],q次询问,每次问S的子串S[pl..pr]在T[l..r]中的哪个串里的出现次数最多,并输出出现次数。
如有多解输出最靠前的那一个。
解:
什么奇葩排版......
对T建广义SAM,线段树合并维护每个节点有哪些串。写法稍微注意一下。
记录下s在t上匹配的时候每个前缀走到哪个位置。然后树上倍增找到符合条件的节点,线段树上查询。
如果查到0或者根本没那么长的匹配长度,输出"L 0"
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <algorithm> 6 7 const int N = 500010, M = 20000010; 8 9 struct Edge { 10 int nex, v; 11 }edge[N * 2]; int tp; 12 13 char str[N]; 14 int tr[N * 2][26], len[N * 2], fail[N * 2], tot = 1, n, m, L, R, e[N * 2], cnt; 15 std::string ss[N]; 16 int large[M], ans[M], rt[N * 2], ls[M], rs[M], pos[N], lenth[N], fa[N * 2][20], pw[N * 2]; 17 18 inline void add(int x, int y) { 19 tp++; 20 edge[tp].v = y; 21 edge[tp].nex = e[x]; 22 e[x] = tp; 23 return; 24 } 25 26 inline void Max(int &a, int b) { 27 if(!b) return; 28 if(large[b] > large[a] || (large[b] == large[a] && ans[a] > ans[b])) { 29 a = b; 30 } 31 return; 32 } 33 34 inline void pushup(int o) { 35 large[o] = std::max(large[ls[o]], large[rs[o]]); 36 if(large[ls[o]] > large[rs[o]]) { 37 ans[o] = ans[ls[o]]; 38 } 39 else if(large[rs[o]] > large[ls[o]]) { 40 ans[o] = ans[rs[o]]; 41 } 42 else ans[o] = std::min(ans[ls[o]], ans[rs[o]]); 43 return; 44 } 45 46 inline void insert(int p, int l, int r, int &o) { 47 if(!o) o = ++cnt; 48 if(l == r) { 49 ans[o] = r; 50 large[o]++; 51 return; 52 } 53 int mid = (l + r) >> 1; 54 if(p <= mid) insert(p, l, mid, ls[o]); 55 else insert(p, mid + 1, r, rs[o]); 56 pushup(o); 57 return; 58 } 59 60 inline int merge(int x, int y, int l, int r) { 61 if(!x || !y) return x | y; 62 if(l == r) { 63 int o = ++cnt; 64 large[o] = large[x] + large[y]; 65 ans[o] = r; 66 return o; 67 } 68 int o = ++cnt, mid = (l + r) >> 1; 69 ls[o] = merge(ls[x], ls[y], l, mid); 70 rs[o] = merge(rs[x], rs[y], mid + 1, r); 71 pushup(o); 72 return o; 73 } 74 75 void out(int l, int r, int x) { 76 if(!x) printf("!x"); 77 printf("(%d [%d %d] lar=%d ans=%d) ", x, l, r, large[x], ans[x]); 78 if(l == r) { 79 printf("%d ", r); 80 return; 81 } 82 int mid = (l + r) >> 1; 83 if(ls[x]) out(l, mid, ls[x]); 84 if(rs[x]) out(mid + 1, r, rs[x]); 85 return; 86 } 87 88 void DFS(int x) { 89 for(int i = e[x]; i; i = edge[i].nex) { 90 int y = edge[i].v; 91 DFS(y); 92 rt[x] = merge(rt[x], rt[y], 1, m); 93 } 94 return; 95 } 96 97 inline int ask(int l, int r, int o) { /// return a Node 98 if(!o) return 0; 99 if(L <= l && r <= R) return o; 100 int mid = (l + r) >> 1, Ans = 0; 101 if(L <= mid) Max(Ans, ask(l, mid, ls[o])); 102 if(mid < R) Max(Ans, ask(mid + 1, r, rs[o])); 103 return Ans; 104 } 105 106 inline int split(int p, int f) { 107 int Q = tr[p][f], nQ = ++tot; 108 len[nQ] = len[p] + 1; 109 fail[nQ] = fail[Q]; 110 fail[Q] = nQ; 111 memcpy(tr[nQ], tr[Q], sizeof(tr[Q])); 112 while(tr[p][f] == Q) { 113 tr[p][f] = nQ; 114 p = fail[p]; 115 } 116 return nQ; 117 } 118 119 inline int insert(char c, int p, int id) { 120 int f = c - 'a', np; 121 if(tr[p][f]) { 122 int Q = tr[p][f]; 123 if(len[Q] == len[p] + 1) { 124 np = Q; 125 } 126 else np = split(p, f); 127 insert(id, 1, m, rt[np]); 128 return np; 129 } 130 np = ++tot; 131 len[np] = len[p] + 1; 132 while(p && !tr[p][f]) { 133 tr[p][f] = np; 134 p = fail[p]; 135 } 136 if(!p) { 137 fail[np] = 1; 138 } 139 else { 140 int Q = tr[p][f]; 141 if(len[Q] == len[p] + 1) { 142 fail[np] = Q; 143 } 144 else { 145 fail[np] = split(p, f); 146 } 147 } 148 insert(id, 1, m, rt[np]); 149 return np; 150 } 151 152 inline int getpos(int l, int r) { 153 int p = pos[r], Len = r - l + 1; 154 if(lenth[r] < Len) return 0; 155 int t = pw[tot]; 156 while(t >= 0) { 157 if(len[fa[p][t]] >= Len) { 158 p = fa[p][t]; 159 } 160 t--; 161 } 162 return p; 163 } 164 165 int main() { 166 scanf("%s", str + 1); 167 n = strlen(str + 1); 168 scanf("%d", &m); 169 for(int i = 1; i <= m; i++) { 170 std::cin >> ss[i]; 171 int k = ss[i].size(), p = 1; 172 for(int j = 0; j < k; j++) { 173 p = insert(ss[i][j], p, i); 174 } 175 } 176 /// insert OVER 177 for(int i = 2; i <= tot; i++) { 178 add(fail[i], i); 179 fa[i][0] = fail[i]; 180 } 181 DFS(1); 182 for(int i = 2; i <= tot; i++) pw[i] = pw[i >> 1] + 1; 183 for(int j = 1; j <= pw[tot]; j++) { 184 for(int i = 1; i <= tot; i++) { 185 fa[i][j] = fa[fa[i][j - 1]][j - 1]; 186 } 187 } 188 int Len = 0, p = 1; 189 for(int i = 1; i <= n; i++) { 190 int ff = str[i] - 'a'; 191 while(p && !tr[p][ff]) { 192 p = fail[p]; 193 Len = len[p]; 194 } 195 if(!p) { 196 p = 1; 197 } 198 else { 199 p = tr[p][ff]; 200 Len++; 201 } 202 pos[i] = p; 203 lenth[i] = Len; 204 } 205 /// prework OVER 206 int q, l, r; 207 scanf("%d", &q); 208 for(int i = 1; i <= q; i++) { 209 scanf("%d%d%d%d", &L, &R, &l, &r); 210 p = getpos(l, r); 211 if(!p) printf("%d 0 ", L); 212 else { 213 int Ans = ask(1, m, rt[p]); 214 if(!Ans) printf("%d 0 ", L); 215 else printf("%d %d ", ans[Ans], large[Ans]); 216 } 217 } 218 return 0; 219 }
我调了一晚上差点气疯了,结果是因为tr数组第二维只开了2...这个数组脱离我的控制...