BZOJ4566 Haoi2016 找相同字元

2022-03-29 20:26:50 字數 2171 閱讀 9792

bzoj4566: [haoi2016]找相同字元

給定兩個字串,求出在兩個字串中各取出乙個子串使得這兩個子串相同的方案數。

兩個方案不同當且僅當這兩個子串中有乙個位置不同。

兩行,兩個字串s1,s2,長度分別為n1,n2。

1 <=n1, n2<= 200000,字串中只有小寫字母

輸出乙個整數表示答案

aabb

bbaa

10題解here!

​$o(n^3)$的大暴力:

首先,我們知道。如果連個串中各取乙個極長的相同的子串(極長的意思就是這兩個串再向兩邊延伸就會不同或出界),則這個極長的串的所有子串也是相同的。

由於列舉極長的串並求出其長度並不方便,所以我們可以列舉這個極長的串的左端點,再求出其長度。

這樣就可以不重不漏找出所有的極長的串。

更圖方便的話,我們可以只考慮兩原串中某字尾的所有字首,這可以補充不漏找出所有的子串。

但是由於我們要在兩個字串中列舉,同時找出子串的長度也是$o(n)$的,於是總複雜度為$o(n^3)$。

$o(n^2)$的優化大暴力:

​剛才說道了字尾的字首,我們不由自主想到了字尾陣列。

如果我們可以很快求出$a$串和$b$串的某兩個字尾的最長公共字首,我們就可以將時間複雜度優化的更低。

這不就是$height$陣列解決的嘛!

所以我們可以將兩個字串通過乙個分隔符拼接起來,求出$height$陣列,即按字典序排序後每個字尾和前乙個的$lcp$。

再利用$height$陣列和$st$表,我們就可以$o(1)$得到任意兩字尾的$lcp$。

因此,這樣做的時間複雜度只有列舉子串起點的複雜度了,即$o(n^2)$。

$o(nlog_2n)$的正解:

​現在拉高時間複雜度的罪魁禍首就是列舉起點了。

所以我們想將其複雜度降低。

考慮到利用$height$陣列求任意兩個字尾的$lcp$時的獨特性質:

兩個字尾的$lcp$為字典序排序後他們中間夾的最小的$height$。

也就是說排序後,乙個字尾越往後數$lcp$的長度越小。

這樣,我們就可以用單調棧維護這個最小值。

分$a$串的子串在前、$b$的子串在前兩種情況分別用單調棧求出答案,加起來就行。

至於如何維護,emmm......

​ 由於利用了單調棧這個神奇的手段,時間複雜度降到了$o(nlog_2n)$,也就是倍增處理字尾陣列的複雜度。

當然你可以用$dc3$來完成,複雜度可以降到$o(n)$。(當然,本蒟蒻不會啦。。。)

附**:

#include#include#include#include#define maxn 400010

using namespace std;

pairstack[maxn];

int n,l1,l2;

int val[maxn],sum[maxn];

char str[maxn];

int top,sa[maxn],rk[maxn],tax[maxn],tp[maxn],height[maxn];

inline int read()

while(c>='0'&&c<='9')

return date*w;

}void radixsort()

void suffixsort()

radixsort();

for(int w=1,p=0;pw)tp[++p]=sa[i]-w;

radixsort();

swap(tp,rk);

rk[sa[1]]=p=1;

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

rk[sa[i]]=(tp[sa[i-1]]==tp[sa[i]]&&tp[sa[i-1]+w]==tp[sa[i]+w])?p:++p;

}}void getheight()

}void work()

top=0;

for(int i=1;i<=n;i++)sum[i]=sum[i-1]+(sa[i]>l1+1);

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

while(top&&height[i]以上是字尾陣列解法,當然你可以用$sam$吊打$sa$,就像$ac$自動機吊打$trie$和$kmp$一樣。。。

(坑,未填。。。)

bzoj4566 HAOI2016 找相同字元

time limit 20 sec memory limit 256 mb submit 113 solved 64 submit status discuss description 給定兩個字串,求出在兩個字串中各取出乙個子串使得這兩個子串相同的方案數。兩個方案不同當且僅當這兩 個子串中有乙個位...

BZOJ4566 HAOI2016 找相同字元

bzoj luogu 首先把兩個串拼在一起跑字尾陣列。中間插入乙個沒有出現過的字元。求完字尾陣列之後考慮 o n 2 暴力統計 列舉前乙個串和後乙個串的兩個位置,ans lcp i,j 現在改為把一共 2n 個字尾按 rank 順序插入,每插入乙個字尾,統計與其不在同乙個串裡的字尾的貢獻。發現可以單...

bzoj4566 Haoi2016 找相同字元

time limit 20 sec memory limit 256 mb給定兩個字串,求出在兩個字串中各取出乙個子串使得這兩個子串相同的方案數。兩個方案不同當且僅當這兩 個子串中有乙個位置不同。兩行,兩個字串s1,s2,長度分別為n1,n2。1 n1,n2 200000,字串中只有小寫字母 輸出乙...