题意

给定一个长度为 nn 的字符串 TT,按照以下规则生成一组字符串 S1nS_{1\sim n}:若 TiT_i 为小写,Si=Ti+Si1S_i=T_i+S_{i-1},否则 Si=Si1+lower(Ti)S_i=S_{i-1}+lower(T_i).

给定一个长度为 mm 的序列 ppqq 次询问,求 pp 上区间 lrl\sim r 中最小的为 SkS_k 的周期的数。

思路

首先发现一个关键性质,若一个长度不为 SiS_i 的周期,那它一定不为 Sj(ij)S_j(i\le j) 的周期。

iiS[i,ti]S_{[i,t_i]} 的周期,可以考虑二分找到 tit_i.

然后可以使用线段树激活的方法,将 pp 中的值按照 tpit_{p_i} 从大到小加入线段树中,将询问离线下来统计答案。

tips:本题似乎卡哈希(没试过,反正同学被卡了)。

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
#include <bits/stdc++.h>
#define int long long
#define chmax(x, y) x = max(x, y)
#define chmin(x, y) x = min(x, y)
#define SP << " " <<
#define fish signed
using namespace std;
mt19937 rnd(1209);
const int INF = 0x3f3f3f3f3f3f3f3f;
const int base = 66683, N = 1e6 + 10, base2 = 131, mod = 998244353;
unsigned long long prod[N], h[N];
long long prod2[N], h2[N];
unsigned long long get(int l, int r) {return h[r] - h[l - 1] * prod[r - l + 1];}
int get2(int l, int r) {return ((h2[r] - h2[l - 1] * prod2[r - l + 1] % mod) % mod + mod) % mod;}
int sl[N], sr[N], t[N]; char a[N];
int mn[N << 2];
#define ls(u) (u << 1)
#define rs(u) (u << 1 | 1)
void modify(int u, int l, int r, int pos, int k)
{
if(l == r) {
mn[u] = k;
return ;
}
int mid = l + r >> 1;
if(pos <= mid) modify(ls(u), l, mid, pos, k);
else modify(rs(u), mid + 1, r, pos, k);
mn[u] = min(mn[u << 1],mn[u << 1 | 1]);
}
int query(int u, int l, int r, int ql, int qr)
{
if(ql <= l && r <= qr) return mn[u];
int mid = l + r >> 1, res = INF;
if(ql <= mid) chmin(res, query(ls(u), l, mid, ql, qr));
if(qr > mid) chmin(res, query(rs(u), mid + 1, r, ql, qr));
return res;
}
struct node {int l, r, id;} ;
int ans[N];
vector<node> vp[N];
vector<node> vq[N];
fish main()
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int n; cin >> n;
int hh = n + 1, tt = n;
for(int i = 1; i <= n; i ++)
{
char ch; cin >> ch;
if('A' <= ch && ch <= 'Z') a[++ tt] = ch - 'A' + 'a';
else a[-- hh] = ch;
sl[i] = hh, sr[i] = tt;
}
prod[0] = prod2[0] = 1;
for(int i = 1; i <= n; i ++) prod[i] = prod[i - 1] * base;
for(int i = hh; i <= tt; i ++) h[i] = h[i - 1] * base + (unsigned long long)a[i];
for(int i = 1; i <= n; i ++) prod2[i] = (prod2[i - 1] * base2) % mod;
for(int i = hh; i <= tt; i ++) h2[i] = (h2[i - 1] * base2 % mod + a[i]) % mod;
for(int i = 1; i <= n; i ++)
{
int l = i, r = n, res = i;
while(l <= r)
{
int mid = l + r >> 1;
int l1 = sl[mid], l2 = sl[mid] + i;
int r1 = sr[mid] - i, r2 = sr[mid];
if(get(l1, r1) == get(l2, r2) && get2(l1, r1) == get2(l2, r2)) l = mid + 1, res = mid;
else r = mid - 1;
}
t[i] = res;
}
int m; cin >> m;
for(int i = 1; i <= m; i ++) {int x; cin >> x; vp[t[x]].push_back({i, x});}
memset(mn, 0x3f, sizeof mn);
int q; cin >> q;
for(int i = 1; i <= q; i ++) {int k, l, r; cin >> k >> l >> r; vq[k].push_back({l, r, i});}
for(int i = n; i >= 1; i --)
{
for(auto v : vp[i]) modify(1, 1, m, v.l, v.r);
for(auto v : vq[i]) {ans[v.id] = query(1, 1, m, v.l, v.r); if(ans[v.id] > i) ans[v.id] = -1;}
}
for(int i = 1; i <= q; i ++) cout << ans[i] << "\n";
return 0;
}