洛谷 P2408 不同子串個數

2022-09-19 12:18:13 字數 1083 閱讀 1500

鏈結

p2408

題意給你乙個長為 \(n\) 的字串 \(s\),求本質不同的子串的個數。

分析這是乙個經典字串問題。我們難以用 kmp 或 ac 自動機來做,所以只能考慮把 \(s\) 的 sa 跑出來。

這樣任意乙個子串都是 \(s\) 某乙個字尾的乙個字首,由於有 \(ht\) 這樣有用的東西存在,所以我們就直接看排序後的字尾。

我們發現 \(ht\) 陣列是當前字尾與上一字尾的 lcp,也正是相同字首數。比如 \(aa\) 和 \(aaa\) 的 \(ht\) 是 \(2\) 也就是 \(a\) 和 \(aa\) 這兩個相同字首。又因為字尾的字首是原串的子串,所以這裡的 \(ht\) 正是重複的子串數,這啟示我們用總子串數減去重複子串數來得到答案。

但這裡的 \(ht\) 只是當前字尾和前一字尾的重複數,如果還有其他一樣重複的呢?我們發現由於字尾陣列按字典序排序的良好性質,重複的子串在字尾陣列中一定是在一段連續的區間(比如上面的重複子串 \(a\) 就出現在了 \([1,6]\) 的字尾中)。所以 \(ht\) 會將這些所有的重複子串都囊括完。最後我們發現重複子串數就是 \(\sum\limits_^n ht_i\),於是我們的答案就是 \(\frac2-\sum\limits_^n ht_i\)。

**

#includeusing namespace std;

#define int long long

#define in read()

inline int read()

while(isdigit(c))

return p*f;

}const int n=1e5+5;

int n,m,rk[n<<1],sa[n],ht[n];

struct llmmkkst[n<<1],tmp[n<<1];

int cnt[n];

inline void jsort()

int ston[257];

inline void sa(string s)

P2408 不同子串個數 SA LCP SAM

傳送門 經典的sa lc psa lcp sa lcp 題目。顯然所有子串數目為n n 1 2 dfrac 2n n 1 因此我們只需知道重複的子串有多少個。根據l cp lcplc p我們知道利用lcp lcplc p求出的hei ght i l cp i i 1 即排 名第i名 和第i 1名的最...

P 2408 本質不同的字串的個數

1.題目鏈結。求乙個字串本質不同的字串有多少個?本質不同定義為 兩個字串不相等。2.這個問題其實十分的簡單,從字尾陣列的角度來看,對於每乙個sa i 我們知道sa i 代表排名為i的這個字尾所在的位置,假設是j,那麼這個字尾的長度就是n j.他有n j個字首,這些字首都是這個字串的子串,可以證明 所...

luogu P2408 不同子串個數

考慮反向操作,去計算有多少組相同的子串,對於一組大小為k的極大相同子串的集合,ans k 1。為了避免重複計算,需要一種有效的,有順序的記錄方案。比如說,對於每乙個相同組,按其起始點所在的位置排序,對於除了第乙個串以外的串,均記 1的貢獻。但這種東西是非常難以快速統計的。但是,可以對於每乙個相同組,...