I-string_2019牛客暑期多校训练营(第四场)
生活随笔
收集整理的這篇文章主要介紹了
I-string_2019牛客暑期多校训练营(第四场)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意
當a != b且a != rev(b)則認為a串與b串不相等,rev(b)表示b串的反串,例如rev(abcd) = dcba
給出一個串求出該串所有不相等的子串個數
題解
先利用后綴數組求出s#rev(s)的不相等子串個數,再扣掉包含字符‘#’的子串個數,包含‘#’的子串個數為\((len(s)+1)^2\),具體取法為以#及左邊任意字符為起點,以#及右邊字符為終點構成的串,顯然這樣能取出所有包含#的子串,且這些子串都不相等。
所以求出來結果是\(ans = \frac{(2len(s)+1)*(2len(s))}{2}- \sum_{i=2}^{2len(s)+1}height[i]-(len(s)+1)^2\), 這樣求出來的結果是包含a = rev(b)的,比如s = abac,求出來的結果是\({a,b,c,ab,ba,ac,ca,cab,aba,bac,abac,caba}\),可以看出來除了\({a,b,c,aba}\)這幾個回文串,剩余的串都是成對的,那么我們用回文樹求出s本質不同的回文串個數加上之前的ans再除以2就是答案了
代碼
#include <bits/stdc++.h>const int mx = 5e5+5; typedef long long ll; char str[mx];int t1[mx], t2[mx], c[mx]; int sa[mx], rank[mx], height[mx];bool cmp(int *r, int a, int b, int l) {return r[a] == r[b] && r[a+l] == r[b+l]; }void da(int n, int m) {n++;int i, j, p, *x = t1, *y = t2;for (i = 0; i < m; i++) c[i] = 0;for (i = 0; i < n; i++) c[x[i] = str[i]]++;for (i = 1; i < m; i++) c[i] += c[i-1];for (i = n-1; i >= 0; i--) sa[--c[x[i]]] = i;for (j = 1; j <= n; j <<= 1) {p = 0;for (i = n-j; i < n; i++) y[p++] = i;for (i = 0; i < n; i++) if (sa[i] >= j) y[p++] = sa[i] - j;for (i = 0; i < m; i++) c[i] = 0;for (i = 0; i < n; i++) c[x[y[i]]]++;for (i = 1; i < m; i++) c[i] += c[i-1];for (i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];std::swap(x, y);p = 1; x[sa[0]] = 0;for (i = 1; i < n; i++)x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p-1 : p++;if (p >= n) break;m = p;}int k = 0;n--;for (i = 0; i <= n; i++) rank[sa[i]] = i;for (i = 0; i < n; i++) {if (k) k--;j = sa[rank[i]-1];while (str[i+k] == str[j+k]) k++;height[rank[i]] = k;} }const int N = 26; struct pTree {int Next[mx][N];int fail[mx];ll cnt[mx];ll sum[mx];int num[mx];int len[mx];int S[mx];int last, n, p, cur, now;int newnode(int l) {for (int i = 0; i < N; i++) Next[p][i] = 0;cnt[p] = num[p] = 0;len[p] = l;return p++;}void init() {n = p = 0;newnode(0);newnode(-1);last = 0;S[n] = -1;fail[0] = 1;}int getFail(int x) {while (S[n - len[x] - 1] != S[n]) x = fail[x];return x;}bool add(int c) {S[++n] = c;cur = getFail(last);bool flag = false;if (!Next[cur][c]) {flag = true;now = newnode(len[cur] + 2);fail[now] = Next[getFail(fail[cur])][c];Next[cur][c] = now;num[now] = num[fail[now]] + 1;}last = Next[cur][c];cnt[last]++;return flag;}void count() {for (int i = p-1; i >= 0; i--) cnt[fail[i]] += cnt[i];} }tree;int main() {scanf("%s", str);int len = std::strlen(str);str[len] = '#';for (int i = len+1; i <= 2*len; i++) str[i] = str[2*len-i];str[2*len+1] = '\0';int n = 2*len+1;da(n, 128);ll tot = 1LL * (2*len+1) * (2*len+2)/2;tot -= 1LL * (len+1) * (len+1);for (int i = 2; i <= n; i++) tot -= height[i];tree.init();for (int i = 0; i < len; i++) tree.add(str[i]-'a');printf("%lld\n", (tot+tree.p-2)/2);return 0; }轉載于:https://www.cnblogs.com/bpdwn-cnblogs/p/11290646.html
總結
以上是生活随笔為你收集整理的I-string_2019牛客暑期多校训练营(第四场)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: app 崩溃测试 (转:CSDN 我去热
- 下一篇: 【10.4】线程同步--Lock、RLo