CF1043G Speckled Band

CF1043G Speckled Band

CF1043G Speckled Band - 洛谷

Description

给定字符串 S,每次询问 (l,r),将子串 [l,r] 划分为若干段使得至少有两段相同,求拆分后 本质不同的段 的最小个数。

Solution

结果为1 当且仅当子串中每个字符只出现一次,否则可以发现 ans=1/2/3/4

len=rl+1,以下 A,B 表示字符串。

  1. ans=1,此时子串为 AAAA...,枚举 len 的约数 c[l.r] 有长度为 c 的循环节的充要条件为 [l,rc]=[l+c,r]
  2. ans=2,子串为 ABA / AAB / BAA,前者可以求出子串的最短 border 判断;对于后两者,考虑求出 fi, gi 表示以 i 为 开头/结尾 的最短 AA 串长度,那么 fllen or grlen
  3. ans=3,子串为 ABAC / BACA / BAAC,对于前二者,只需要判断 [l,r] 中是否有字符出现超过一次(以它们为 A);后者只需要判断 minlrl+flr
  4. 否则 ans=4

求最短 border

  • 首先枚举长度为 1~nborder,否则最短 border[l,r] 的后缀排名不超过 n
  • 考虑反证法,若 |border|>n 且与 [l,r] 的后缀排名超过 n,则可以证明有更短的 border,与要求矛盾。

fi

  • 方法与 NOI2016 优秀的拆分 类似。
  • 考虑求长度为 2LAA 串,将原串每 L 位设置关键点,则长为 2LAA 串一定经过且只经过两个关键点。
  • 可以以关键点将 A 分为 LCPLCS
  • 求出相邻关键点的 lcplcs ,那么形成 AA 串的充要条件为 lcp+lcs>L,开头区间为 [llcp+1,llen+lcs]
  • g 类似。

Code

复制代码
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
#include <bits/stdc++.h> using namespace std; #define N 200000 #define L 18 #define fo(i, x, y) for(int i = x, end_##i = y; i <= end_##i; i ++) #define fd(i, x, y) for(int i = x, end_##i = y; i >= end_##i; i --) #define mcp(a, b) memcpy(a, b, sizeof b) #define Mes(a, x) memset(a, x, sizeof a) void read(int &x) { char ch = getchar(); x = 0; while (ch < '0' || ch > '9') ch = getchar(); while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + ch - 48, ch = getchar(); } char ch[N + 1]; int n; struct HASH { int h[N + 1], mi[N + 1], inv[N + 1], p, mo; int pw(int x, int k) { int res = 1; while (k) { if (k & 1) res = 1ll * res * x % mo; x = 1ll * x * x % mo; k >>= 1; } return res; } void build(int x, int y) { mo = x, p = y; mi[0] = 1; fo(i, 1, n) mi[i] = 1ll * mi[i - 1] * p % mo; inv[n] = pw(mi[n], mo - 2); fd(i, n, 1) inv[i - 1] = 1ll * inv[i] * p % mo; fo(i, 1, n) h[i] = (h[i - 1] + 1ll * (ch[i] - 'a' + 1) * mi[i] % mo) % mo; } int hash(int l, int r) { return 1ll * (h[r] - h[l - 1] + mo) % mo * inv[l] % mo; } } h1, h2; bool check(int l, int r, int x, int y) { return h1.hash(l, r) == h1.hash(x, y) && h2.hash(l, r) == h2.hash(x, y); } int Log[N + 1]; struct SA { int sa[N + 1], rk[N + 1], ht[N + 1], id[N + 1], oldrk[N << 1], buc[N + 1], px[N + 1], ft[N + 1][L + 1]; int sk; void mysort() { fill(buc, buc + 1 + sk, 0); fo(i, 1, n) ++ buc[ px[i] = rk[id[i]] ]; fo(i, 1, sk) buc[i] += buc[i - 1]; fd(i, n, 1) sa[ buc[px[i]] -- ] = id[i]; } bool pd(int x, int y, int z) { return oldrk[x] == oldrk[y] && oldrk[x + z] == oldrk[y + z]; } void build(char ch[]) { Mes(rk, 0), Mes(oldrk, 0); sk = 26; fo(i, 1, n) rk[ id[i] = i ] = ch[i] - 'a' + 1; mysort(); for (int w = 1, p = 0; w <= n; w <<= 1, p = 0) { fo(i, n - w + 1, n) id[ ++ p ] = i; fo(i, 1, n) if (sa[i] > w) id[ ++ p ] = sa[i] - w; mysort(); mcp(oldrk, rk); sk = 0; fo(i, 1, n) rk[sa[i]] = pd(sa[i], sa[i - 1], w) ? sk : ++ sk; if (sk == n) { fo(i, 1, n) sa[rk[i]] = i; break; } } sk = 0; fo(i, 1, n) { if (sk) -- sk; while (ch[i + sk] == ch[sa[rk[i] - 1] + sk]) ++ sk; ht[rk[i]] = sk; } fo(i, 1, n) ft[i][0] = ht[i]; fo(j, 0, L - 1) fo(i, 1, n) ft[i][j + 1] = (i + (1 << j) <= n) ? min(ft[i][j], ft[i + (1 << j)][j]) : ft[i][j]; } int dt; int get(int l, int r) { l = rk[l], r = rk[r]; if (l > r) swap(l, r); if (++ l == r) return ft[l][0]; dt = Log[r - l + 1]; return min(ft[l][dt], ft[r - (1 << dt) + 1][dt]); } } s1, s2; struct Tree { #define ls (t << 1) #define rs (t << 1 | 1) int vl[N << 2]; Tree() { Mes(vl, 0x3f); } void Add(int t, int l, int r, int x, int y, int k, int lz) { if (lz < vl[t]) vl[t] = lz; if (x <= l && r <= y) { vl[t] = k; return; } int mid = l + r >> 1; if (x <= mid) Add(ls, l, mid, x, y, k, vl[t]); if (y > mid) Add(rs, mid + 1, r, x, y, k, vl[t]); } void fil(int t, int l, int r, int lz, int at[]) { if (lz < vl[t]) vl[t] = lz; if (l == r) { at[l] = vl[t]; return; } int mid = l + r >> 1; fil(ls, l, mid, vl[t], at), fil(rs, mid + 1, r, vl[t], at); } #undef ls #undef rs } t1, t2; int gt[N + 1][L + 1], dl[N + 1], dr[N + 1], sc[N + 1][26]; const int inf = 0x3f3f3f3f; int sqn; void Init() { Log[1] = 0; fo(i, 2, n) Log[i] = Log[i >> 1] + 1; h1.build(998244353, 37); h2.build(1000000007, 29); s1.build(ch); fd(i, (n >> 1), 1) swap(ch[i], ch[n - i + 1]); s2.build(ch); fd(i, (n >> 1), 1) swap(ch[i], ch[n - i + 1]); int l, r, lcp, lcs, dlen, pl, pr; fd(len, (n >> 1), 1) { fd(k, (n / len) - 1, 1) { l = len * k, r = len * (k + 1); lcs = s1.get(l, r); lcp = s2.get(n - l + 1, n - r + 1); if (lcp + lcs > len) { lcp = min(lcp, len), lcs = min(lcs, len); dlen = lcp + lcs - len - 1; t1.Add(1, 1, n, l - lcp + 1, l - lcp + 1 + dlen, (len << 1), inf); t2.Add(1, 1, n, r + lcs - 1 - dlen, r + lcs - 1, (len << 1), inf); } } } t1.fil(1, 1, n, inf, dl), t2.fil(1, 1, n, inf, dr); fo(i, 1, n) { fo(j, 0, 25) sc[i][j] = sc[i - 1][j]; ++ sc[i][ch[i] - 'a']; } fo(i, 1, n) gt[i][0] = i + dl[i] - 1; fo(j, 0, L - 1) fo(i, 1, n) gt[i][j + 1] = (i + (1 << j) <= n) ? min(gt[i][j], gt[i + (1 << j)][j]) : gt[i][j]; sqn = sqrt(n); } bool pd0(int l, int r) { fo(i, 0, 25) if (sc[r][i] - sc[l - 1][i] > 1) return 0; return 1; } int len, sq; bool pd1(int l, int r) { len = r - l + 1, sq = sqrt(len); if (check(l, r - 1, l + 1, r)) return 1; fo(i, 2, sq) if (len % i == 0) if (check(l, r - i, l + i, r) || check(l, r - len / i, l + len / i, r)) return 1; return 0; } int min_ht; bool pd2(int l, int r) { len = r - l + 1; if (dl[l] <= len || dr[r] <= len) return 1; fd(i, min(sqn, (len >> 1)), 1) if (check(l, l + i - 1, r - i + 1, r)) return 1; if (sqn >= (len >> 1)) return 0; min_ht = s1.ht[s1.rk[l]]; fd(i, s1.rk[l] - 1, s1.rk[l] - sqn + 1) { if (i < 1) break; if ((l + r >> 1) < s1.sa[i] && s1.sa[i] <= r && s1.sa[i] + min_ht > r) return 1; min_ht = min(min_ht, s1.ht[i]); } min_ht = len; fo(i, s1.rk[l] + 1, s1.rk[l] + sqn - 1) { if (i > n) break; min_ht = min(min_ht, s1.ht[i]); if ((l + r >> 1) < s1.sa[i] && s1.sa[i] <= r && s1.sa[i] + min_ht > r) return 1; } return 0; } bool pd3(int l, int r) { return (sc[r][ch[l] - 'a'] - sc[l][ch[l] - 'a'] > 0) || (sc[r - 1][ch[r] - 'a'] - sc[l - 1][ch[r] - 'a'] > 0); } int dx; int get_Min_dl(int l, int r) { if (l == r) return gt[l][0]; dx = Log[r - l + 1]; return min(gt[l][dx], gt[r - (1 << dx) + 1][dx]); } int main() { scanf("%d\n%s", &n, ch + 1); Init(); int T, l, r; read(T); while (T --) { read(l), read(r); if (pd0(l, r)) puts("-1"); else if (pd1(l, r)) puts("1"); else if (pd2(l, r)) puts("2"); else if (pd3(l, r) || get_Min_dl(l, r) <= r) puts("3"); else puts("4"); } return 0; }
posted @   buzzhou  阅读(116)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
展开