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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

@bzoj - 3238@ [Ahoi2013]差异

發布時間:2023/12/20 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 @bzoj - 3238@ [Ahoi2013]差异 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • @description@
  • @solution@
  • @accepted code@
  • @details@

@description@

給定一個長度為 n 的字符串 S,令 Ti 表示它從第 i 個字符開始的后綴。求:
\[\sum_{1\le i < j \le n}((len(Ti) -lcp(Ti, Tj)+(len(Tj)-lcp(Ti, Tj))\]
其中 lcp 是最長公共前綴。

input
一個長度為 n 的字符串S。2 <= n <= 500000,S由小寫英文字母組成。
output
一個整數,表示所求值。

sample input
cacao
sample output
54

@solution@

那個式子我們可以分兩部分求解:len 和 lcp。

len 部分:每一個后綴的 len 都會統計 n-1 次。所以它對答案的貢獻為 \((1+2+...+n)*(n-1)\)。把等差數列的求和公式代進去:\(\frac{(n-1)*n*(n+1)}{2}\)

lcp 部分:我們把原串翻轉,則原串中的后綴對應新串中的前綴,我們要求解原串中的最長公共前綴就是新串中的最長公共后綴。
一個結點的 fa 所表示的結點一定是這個結點的后綴。所以我們最長公共后綴所表示的結點一定是該結點的某個祖先。
那么兩個結點的 lca 就能表示它們的最長公共后綴。因此我們作一個簡單的樹形 dp 統計有多少對點以根為 lca 即可。

實際上,后綴自動機在翻轉的串上建出來的 parent 樹,就是原串中的后綴樹。

所以后綴樹完完全全沒什么用啊喂。

@accepted code@

#include<vector> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int MAXN = 500000; vector<int>G[2*MAXN + 5]; struct sam{sam *ch[26], *fa; int mx;int tag; }pl[2*MAXN + 5], *root, *tcnt, *lst; void init() {root = tcnt = lst = &pl[0]; } sam *newnode(int x) {tcnt++; tcnt->tag = x;return tcnt; } void clone(sam *x, sam *y) {for(int i=0;i<26;i++)x->ch[i] = y->ch[i];x->fa = y->fa; } void sam_extend(int x) {sam *cur = newnode(1), *p = lst;cur->mx = lst->mx + 1; lst = cur;while( p && !p->ch[x] )p->ch[x] = cur, p = p->fa;if( !p )cur->fa = root;else {sam *q = p->ch[x];if( p->mx + 1 == q->mx )cur->fa = q;else {sam *nq = newnode(0);nq->mx = p->mx + 1;clone(nq, q);q->fa = cur->fa = nq;while( p && p->ch[x] == q )p->ch[x] = nq, p = p->fa;}} } int siz[2*MAXN + 5]; char s[MAXN + 5]; ll ans; void dfs(int rt) {siz[rt] = pl[rt].tag;for(int i=0;i<G[rt].size();i++) {int to = G[rt][i]; dfs(to);ans -= 2LL*siz[rt]*siz[to]*pl[rt].mx;siz[rt] += siz[to];} } int main() {init(); scanf("%s", s);int lens = strlen(s);ans = 1LL*(lens-1)*lens*(lens+1)/2;for(int i=lens-1;i>=0;i--)sam_extend(s[i] - 'a');for(int i=1;i<=tcnt-pl;i++) {G[pl[i].fa-pl].push_back(i);} dfs(0);printf("%lld\n", ans); }

@details@

所以真的想問問大家,后綴樹既然可以通過后綴自動機構造出來,時間復雜度空間復雜度也不會更優秀(因為你不可能超過線性復雜度嘛)。

那么后綴樹到底用處在哪里?

轉載于:https://www.cnblogs.com/Tiw-Air-OAO/p/10256459.html

總結

以上是生活随笔為你收集整理的@bzoj - 3238@ [Ahoi2013]差异的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。