题解:String
前言
我的 std 做法很蠢。
你可以选择用高级的线段树合并做掉它,并且良心出题人没有强制在线。
再次感谢 sunset_breeze 给出的线段树合并解法,Vector 给出的非随机数据下的解法。
solution
对
将长度为
时间复杂度
std
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 5;
int n, q;
char a[N];
int len[N], fail[N], ch[N][27], cur, pos, tot = 1;
inline int getfail (int x, int i) {
while (i - len[x] - 1 < 0 || a[i - len[x] - 1] != a[i]) x = fail[x];
return x;
}
vector <int> e[N], lnk[N];
int f[N][21], dep[N], down[N];
inline void dfs (int x, int fa) {
f[x][0] = fa, dep[x] = dep[fa] + 1;
for (int i = 1; i <= 19; ++ i) f[x][i] = f[f[x][i - 1]][i - 1];
for (auto v : e[x]) {
if (v == fa) continue;
dfs (v, x);
}
return ;
}
signed main () {
ios::sync_with_stdio (0);
cin.tie (0), cout.tie (0);
cin >> n >> q;
cin >> (a + 1);
fail[0] = 1, len[1] = -1;
e[0].push_back (1), e[1].push_back (0);
for (int i = 1; i <= n; ++ i) {
pos = getfail (cur, i);
if (!ch[pos][a[i] - 'a']) {
fail[++ tot] = ch[getfail (fail[pos], i)][a[i] - 'a'];
e[fail[tot]].push_back (tot), e[tot].push_back (fail[tot]);
ch[pos][a[i] - 'a'] = tot;
len[tot] = len[pos] + 2;
down[tot] = i - len[tot] + 1;
lnk[len[tot]].push_back (tot);
}
cur = ch[pos][a[i] - 'a'];
}
dfs (1, 1);
dfs (0, 0);
for (int i = 1, l, r; i <= q; ++ i) {
cin >> l >> r;
int ans = n + 1;
for (auto x : lnk[r]) {
int val = down[x];
for (int i = 19; i >= 0; -- i) if (len[f[x][i]] >= l) x = f[x][i];
if (len[x] == l) {
ans = min (ans, val);
break;
}
}
if (ans != n + 1) cout << ans << "\n";
else cout << "-1\n";
}
return 0;
}