BZOJ 3473 字串 廣義字尾自動機

2022-04-06 20:37:43 字數 1683 閱讀 7414

time limit: 20 sec  memory limit: 256 mb

submit: 354  solved: 160

[submit][status][discuss]

給定n個字串,詢問每個字串有多少子串(不包括空串)是所有n個字串中至少k個字串的子串?

第一行兩個整數n,k。

接下來n行每行乙個字串。

一行n個整數,第i個整數表示第i個字串的答案。

字串總長度l

n,k,l<=1e5

研究了兩節多課廣義字尾自動機是什麼,還看了2015國家隊**,然後發現,廣義字尾自動機不就是把很多串的sam建到了乙個sam上,建每個串的時候都從root開始(last=root)就行了........

廣義字尾自動機是trie樹的字尾自動機,可以解決多主串問題

還有一種離線演算法,複雜度o(|t||a|) ,不學了吧

對於本題,建出廣義sam後,只要得到每個狀態出現在不同串中的次數就好做了

我們跑每個子串,然後更新狀態

狀態維護cou和cur分別為出現次數及上一次出現是哪個串,然後就可以不重複的統計啦

出現次數向父親傳遞,所以要沿著parent向上跑更新,遇到cur=當前串的就不用繼續跑了,這樣最壞情況下複雜度為o(l^3/2),發生在n=l的時候(均值不等式啊)

剩下的只要dp出f[i]為i及其parent祖先出現次數》=k有多少字串(注意乙個狀態貢獻的字串為t[par].val-t[u].val),然後在跑一遍每個字串得到答案就行了

注意sz也要=1啊啊啊啊啊啊啊啊啊再讓你作死寫新模板

#include #include 

#include

#include

#include

#include

using

namespace

std;

const

int n=2e5+5

;typedef

long

long

ll;int

n,k;

string s[n>>1

];char ss[n>>1

];struct

nodet[n];

int sz=1,root=1,last=1

;void extend(int

c) }

last=np;

}int

c[n],a[n];

ll f[n];

void

radixsort()

void

solve()

}radixsort();

for(int i=1;i<=sz;i++) u=a[i];

t[1].cou=0

;

for(int i=1;i<=sz;i++) u=a[i],f[u]=f[t[u].par]+(t[u].cou>=k?t[u].val-t[t[u].par].val:0

);

for(int i=1;i<=n;i++)

printf(

"%lld

",ans);

}}int

main()

solve();

}

BZOJ3473 字串 廣義字尾自動機

今天主攻了下sam 好多東西以前都沒理解到 對於這道題 我們建乙個自動機存所有串 每個穿last從1開始 對於自動機上每個點額外記乙個cnt 表示能匹配到這個點的不同串個數 建完對每個串在自動機上匹配 把到的每個點x和par x par par x 的cnt 然後就從父親往兒子傳遞一下 這樣每個點i...

KMP 字串 BZOJ4974字串大師

在kmp演算法中,fai lfail fail 指標有乙個特殊的性質,i f aili i fail i i fail i 是前i個字元的最小迴圈節大小。所以這題相當於就是說,給了你每個點的fail指標,求乙個滿足的字串。那麼按照建fail指標的方式倒過來做就好了 include include i...

BZOJ4974 字串大師

不難發現結論pe ri i nex ti,nex t 就是kmp裡的失配陣列。考慮構造乙個字串 s 滿足上述ne xt陣列,定義 i 的失配集為 n exti 1 1 的失配集。若ne xti 0 則si sne xti 若ne xti 0 則 i 必須和其失配集中的字元互不相同,因為字典序要最小,...