日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

I-string_2019牛客暑期多校训练营(第四场)

發(fā)布時(shí)間:2025/3/21 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 I-string_2019牛客暑期多校训练营(第四场) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

題意

當(dāng)a != b且a != rev(b)則認(rèn)為a串與b串不相等,rev(b)表示b串的反串,例如rev(abcd) = dcba
給出一個(gè)串求出該串所有不相等的子串個(gè)數(shù)

題解

先利用后綴數(shù)組求出s#rev(s)的不相等子串個(gè)數(shù),再扣掉包含字符‘#’的子串個(gè)數(shù),包含‘#’的子串個(gè)數(shù)為\((len(s)+1)^2\),具體取法為以#及左邊任意字符為起點(diǎn),以#及右邊字符為終點(diǎn)構(gòu)成的串,顯然這樣能取出所有包含#的子串,且這些子串都不相等。
所以求出來(lái)結(jié)果是\(ans = \frac{(2len(s)+1)*(2len(s))}{2}- \sum_{i=2}^{2len(s)+1}height[i]-(len(s)+1)^2\), 這樣求出來(lái)的結(jié)果是包含a = rev(b)的,比如s = abac,求出來(lái)的結(jié)果是\({a,b,c,ab,ba,ac,ca,cab,aba,bac,abac,caba}\),可以看出來(lái)除了\({a,b,c,aba}\)這幾個(gè)回文串,剩余的串都是成對(duì)的,那么我們用回文樹(shù)求出s本質(zhì)不同的回文串個(gè)數(shù)加上之前的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; }

轉(zhuǎn)載于:https://www.cnblogs.com/bpdwn-cnblogs/p/11290646.html

總結(jié)

以上是生活随笔為你收集整理的I-string_2019牛客暑期多校训练营(第四场)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。