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 必須和其失配集中的字元互不相同,因為字典序要最小,...