欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 国际 > CF1098F Ж-function

CF1098F Ж-function

2025/1/30 18:19:37 来源:https://blog.csdn.net/zsyzClb/article/details/145395931  浏览:    关键词:CF1098F Ж-function

【题意】
给你一个字符串 s s s,每次询问给你 l , r l, r l,r,让你输出 s s = s l , r ss=s_{l,r} ss=sl,r ∑ i = 1 r − l + 1 L C P ( s s i , s s 1 ) \sum_{i=1}^{r-l+1}LCP(ss_i,ss_1) i=1rl+1LCP(ssi,ss1)

【思路】
和前一道题一样,用了根号做法。

可以把贡献拆成两部分,第一部分是求原串中的LCP之和,显然这样有一些超过 r r r,而这些都是border,然后就用[BJWC2018] Border 的四种求法的方法来修正这一部分的贡献即可。

第一部分先用SA,然后正着扫反着扫用分块维护。

第二部分就在前一题的基础上多进行一些对长度的分类讨论就行。

#include <bits/stdc++.h>
#define ll long long
using namespace std;const int N = 2e5 + 10, B = 250;
const int mod = 1e9 + 7;int n, m; char s[N];
int sa[N], rk[N], height[N], st[N][20], lg[N];
vector<pair<int, int>> ask[N];
ll ans[N];
int val[N], hsh[N];
int period[N], nxt[N], jump[N], to[N], f[N];void SA() {vector<int> x(N), y(N), c(N);int m = 256;for (int i = 1; i <= n; i++) c[x[i] = s[i]]++;for (int i = 1; i <= m; i++) c[i] += c[i - 1];for (int i = n; i >= 1; i--) sa[c[x[i]]--] = i;for (int k = 1; k <= n; k <<= 1) {int num = 0;for (int i = n - k + 1; i <= n; i++) y[++num] = i;for (int i = 1; i <= n; i++) if (sa[i] > k) y[++num] = sa[i] - k;for (int i = 1; i <= m; i++) c[i] = 0;for (int i = 1; i <= n; i++) c[x[i]]++;for (int i = 2; i <= m; i++) c[i] += c[i - 1];for (int i = n; i >= 1; i--) sa[c[x[y[i]]]--] = y[i], y[i] = 0;swap(x, y); x[sa[1]] = num = 1;for (int i = 2; i <= n; i++) x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k]) ? num : ++num;if (num == n) break;m = num;}for (int i = 1; i <= n; i++) rk[sa[i]] = i;int k = 0;for (int i = 1; i <= n; i++) {if (rk[i] == 1) continue;if (k) k--;int j = sa[rk[i] - 1];while (i + k <= n && j + k <= n && s[i + k] == s[j + k]) k++;height[rk[i]] = k;}lg[0] = -1;for (int i = 1; i <= n; i++) {st[i][0] = height[i];lg[i] = lg[i >> 1] + 1;}for (int j = 1; j <= 18; j++) {for (int i = 1; i + (1 << j) - 1 <= n; i++) {st[i][j] = min(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);}}
}
int getlcp(int i, int j) {i = rk[i], j = rk[j];if (i > j) swap(i, j);i++;int t = lg[j - i + 1];return min(st[i][t], st[j - (1 << t) + 1][t]);
}namespace block {int cnt, L[N / B + 10], R[N / B + 10], belong[N];int siz[N / B + 10], num[N / B + 10][B + 10], val[N / B + 10][B + 10];ll sum[N / B + 10];bool vis[N];void init() {cnt = 0;memset(siz, 0, sizeof(siz));memset(num, 0, sizeof(num));memset(val, 0, sizeof(val));memset(sum, 0, sizeof(sum));memset(vis, 0, sizeof(vis));for (int l = 1, r; l <= n; l = r + 1) {r = min(n, l + B - 1);cnt++;L[cnt] = l, R[cnt] = r;for (int i = l; i <= r; i++) {belong[i] = cnt;}}}void limit(int x) {for (int i = 1; i <= cnt; i++) {int tot = 0;while (siz[i] && val[i][siz[i]] >= x) {tot += num[i][siz[i]];sum[i] -= 1ll * num[i][siz[i]] * val[i][siz[i]];siz[i]--;}if (tot) {siz[i]++;num[i][siz[i]] = tot;val[i][siz[i]] = x;sum[i] += 1ll * tot * x;}}}ll calc(int l, int r) { // l < rl++;ll ret = 0;if (belong[l] == belong[r]) {for (int i = l; i <= r; i++) if (vis[i]) {ret += getlcp(l - 1, i);}}else {int t;t = belong[r];for (int i = L[t]; i <= r; i++) if (vis[i]) {ret += getlcp(l - 1, i);}r = L[t] - 1;t = belong[l];for (int i = l; i <= R[t]; i++) if (vis[i]) {ret += getlcp(l - 1, i);}l = R[t] + 1;while (l <= r) {ret += sum[belong[l]];l += B;}}return ret;}void ins(int pos) {vis[pos] = 1;int len = n - pos + 1;int t = belong[pos];sum[t] += len;for (int i = 1; i <= siz[t]; i++) {if (val[t][i] == len) {num[t][i]++;return;}}siz[t]++;num[t][siz[t]] = 1;val[t][siz[t]] = len;for (int i = siz[t]; i > 1; i--) {if (val[t][i] < val[t][i - 1]) {swap(val[t][i], val[t][i - 1]);swap(num[t][i], num[t][i - 1]);}else {break;}}}
}int gethsh(int l, int r) {return (hsh[r] - 1ll * hsh[l - 1] * val[r - l + 1] % mod + mod) % mod;
}ll getsum(int a1, int d, int n) {return 1ll * a1 * n - 1ll * d * n * (n - 1) / 2;
}int main() {// freopen("in.in", "r", stdin);// freopen("out.out", "w", stdout);ios::sync_with_stdio(false);cin.tie(nullptr);clock_t start = clock();cin >> (s + 1) >> m;n = strlen(s + 1);SA();// for (int i = 1; i <= n; i++) {//     cout << sa[i] << " \n"[i == n];// }// for (int i = 1; i <= n; i++) {//     cout << height[i] << " \n"[i == n];// }for (int i = 1; i <= m; i++) {int l, r; cin >> l >> r;ans[i] = r - l + 1;if (l < r) ask[l].push_back({r, i});}block::init();for (int ki = 1; ki <= n; ki++) {block::limit(height[ki]);   int l = sa[ki]; for (auto [r, id] : ask[l]) {ans[id] += block::calc(l, r);}block::ins(l);}block::init();height[n + 1] = 0;for (int ki = n; ki >= 1; ki--) {block::limit(height[ki + 1]);   int l = sa[ki]; for (auto [r, id] : ask[l]) {ans[id] += block::calc(l, r);}block::ins(l);}val[0] = 1;for (int i = 1; i <= n; i++) {val[i] = 1ll * val[i - 1] * 257 % mod;hsh[i] = (1ll * hsh[i - 1] * 257 + s[i] - 'a') % mod;}map<int, int> last;for (int i = 1; i <= n; i++) nxt[i] = n + 1;for (int ki = 1; ki <= n - B + 1; ki++) {f[ki] = ki - 1;for (int i = ki + 1, j = ki - 1; i <= ki + B - 1; i++) {while (j > ki - 1 && s[j + 1] != s[i]) j = f[j];if (s[j + 1] == s[i]) j++;f[i] = j;}period[ki] = ki + B - 1 - f[ki + B - 1];int now = gethsh(ki, ki + B - 1);if (last[now]) nxt[last[now]] = ki;last[now] = ki;}last.clear();for (int i = 1; i <= n; i++) jump[i] = i;for (int i = n - B + 2; i <= n + 1; i++) to[i] = n;for (int i = n - B + 1; i >= 1; i--) {int j = i + period[i];if (j <= n && nxt[i] == j) to[i] = to[j], jump[i] = jump[j];else {for (int j = i + B - 1, k = i + (B - 1) % period[i]; j <= n; j++) {if (s[j] != s[k]) break;to[i] = j;k++; if (k == i + period[i]) k = i;}}}// clock_t end = clock();// cout << (double)(end - start) / CLOCKS_PER_SEC << endl;for (int l = 1; l < n; l++) {for (auto [r, id] : ask[l]) {ll ret = 0;if (r - l + 1 <= 2 * B) {for (int i = l + 1; i <= r; i++) {int t = r - i + 1;if (gethsh(l, l + t - 1) == gethsh(i, r)) {ret -= getlcp(l, i);ret += t;}}}else {for (int t = 1; t < B; t++) {if (gethsh(l, l + t - 1) == gethsh(r - t + 1, r)) {ret -= getlcp(l, r - t + 1);ret += t;}}int x = nxt[l];int len = period[l];int count = 0;while (to[x] < r) {// assert((++count) <= 500);if (to[x] - x >= to[l] - l && (to[x] - x) % len == (to[l] - l) % len) {x = to[x] - (to[l] - l);int t = r - x + 1;if (gethsh(l, l + t - 1) == gethsh(x, r)) {ret -= getlcp(l, x);ret += t;}}x = nxt[jump[x]];}if (x + B - 1 <= r) {int len1 = to[l] - l + 1;int len2 = to[x] - x + 1;//>int t;if (x + len1 - 1 < r) {t = (r - x - len1) / len + 1;x += t * len;len2 -= t * len;}if (x + B - 1 <= r && len2 > len1) { //x + len1 - 1 >= rt = min(len2 - len1 - 1, r - B + 1 - x) / len + 1;ret -= 1ll * (to[l] - l + 1) * t;ret += getsum(r - x + 1, len, t);len2 -= len * t;x += len * t;}//==if (x + B - 1 <= r && len1 == len2) {ret -= getlcp(l, x);ret += r - x + 1;len2 -= len;x += len;}//<if (x + B - 1 <= r) {t = (r - B + 1 - x) / len + 1;ret += 1ll * (r - to[x]) * t;}}}ans[id] += ret;}}// clock_t end2 = clock();// cout << (double)(end2 - end) / CLOCKS_PER_SEC << endl;// cout << (double)(end2 - start) / CLOCKS_PER_SEC << endl;for (int i = 1; i <= m; i++) {cout << ans[i] << "\n";}// clock_t end3 = clock();// cout << (double)(end3 - start) / CLOCKS_PER_SEC << endl;
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com