2021ccpc女生赛 B.攻防演练 倍增
Posted kaka0010
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021ccpc女生赛 B.攻防演练 倍增相关的知识,希望对你有一定的参考价值。
原题链接:https://codeforces.ml/gym/103389/problem/B
题意
给定一个字符串,每次询问区间 [ l , r ] [l,r] [l,r],求一个串T的最小长度,使得T不等于任何区间内的子串
分析
如果是求子串,我们一般采用遍历的方式,记录当前位置的下一个字符的出现位置,然后一直往后跳,如果最后落点在r之内,说明区间有效。那么反过来想,我们如果从l-1的位置开始往后跳,当跳出r的那一刻结束,这样跳的步数也就是最短子串的长度。
因此思路清晰起来,我们记录一个 n x t [ i ] [ j ] nxt[i][j] nxt[i][j]代表当前i位置,下一个j字符出现的最近距离。再记录一个 f [ i ] f[i] f[i]代表从i位置起跳可以跳到的最远位置,也就是 m a x ∑ j = 0 26 n x t [ i ] [ j ] max\\sum_{j=0}^{26}nxt[i][j] max∑j=026nxt[i][j]。那么用倍增数组处理一下 f [ i ] [ 20 ] f[i][20] f[i][20],接着就是老套路了。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;
const ll inf = 1e18;
const int N = 2e5 + 10;
const int M = 1e6 + 10;
const double eps = 1e-8;
const int mod = 998244353;
#define fi first
#define se second
#define re register
#define lowbit (-x&x)
#define endl '\\n'
int n, m;
char s[N];
int nxt[N][26];
int f[N][20];
int pos[26];
void solve() {
cin >> m >> n;
cin >> (s + 1);
for (int i = 0; i < 26; i++) nxt[n][i] = n + 1;
for (int i = n; i >= 1; i--) {
if (!pos[s[i]-'a']) nxt[i][s[i]-'a'] = n + 1;
else nxt[i][s[i]-'a'] = pos[s[i]-'a'];
pos[s[i]-'a'] = i;
for (int j = 0; j < m; j++) {
if (pos[j]) nxt[i-1][j] = pos[j];
else nxt[i-1][j] = n + 1;
}
}
for (int i = 0; i <= n; i++) {
int ma = 0;
for (int j = 0; j < m; j++) ma = max(ma, nxt[i][j]);
f[i][0] = ma;
for (int j = 0; j < 20; j++) f[n+1][j] = f[n][j] = n + 1;
}
for (int j = 1; j < 20; j++) {
for (int i = 0; i <= n; i++) {
f[i][j] = f[f[i][j-1]][j-1];
// if (!i) cout << f[i][j] << ' ' << f[i][j-1] << ' ' << j-1 << endl;
}
}
int q; cin >> q;
while (q--) {
int l, r; cin >> l >> r;
int ans = 0;
int now = l - 1;
for (int i = 19; ~i; i--) {
if (f[now][i] <= r) {
ans += (1 << i);
now = f[now][i];
}
}
printf("%d\\n", ans+1);
}
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
#endif
#ifdef ACM_LOCAL
auto start = clock();
#endif
int t = 1;
// cin >> t;
while (t--)
solve();
#ifdef ACM_LOCAL
auto end = clock();
cerr << "Run Time: " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
#endif
return 0;
}
以上是关于2021ccpc女生赛 B.攻防演练 倍增的主要内容,如果未能解决你的问题,请参考以下文章