HAOI2016 找相同字元

2022-02-05 17:28:12 字數 2781 閱讀 9771

給定兩個字串,求出在兩個字串中各取出乙個子串使得這兩個子串相同的方案數。兩個方案不同當且僅當這兩個子串中有乙個位置不同。

兩行,兩個字串s1,s2,長度分別為n1,n2。1 <=n1, n2<= 200000,字串中只有小寫字母

題解:s1'#'s2拼起來。

求height

要求∑(i)∑(j)lcp(rk[i],rk[j]) 1<=i<=l1, l1+2<=j<=l1+l2+1

考慮找排名序列。

其實是對屬於s1的i之前的,屬於s2的j,min(hei[k]),j+1<=k<=i

對一些前面的某些位置取min再做和

可以分治。

對於跨中點的區間,欽定最小值在左邊,做一遍

欽定最小值在右邊,做一遍

對於兩邊最小值相同的,乙個取等乙個不取等

height[i]=lcp(suff[sa[i],suff[sa[i-1]])

注意邊界處理

#include#define reg register int

#define il inline

#define numb (ch^'0')

using

namespace

std;

typedef

long

long

ll;il

void rd(int &x)

namespace

miracle

if(num==n) break

; m=num;

} }void

gethei()

}ll ans;

int be[2*n];

void divi(int l,int

r)

if(be[i]==1) ans+=(ll)cnt2*mir;

else

if(be[i]==2) ans+=(ll)cnt1*mir;

}cnt1=0,cnt2=0

; ptr=mid+1

;

for(reg i=mid;i>=l;--i)

if(be[i]==1) ans+=(ll)cnt2*mil;

else

if(be[i]==2) ans+=(ll)cnt1*mil;

}divi(l,mid);

divi(mid+1

,r);

}int

main()cout/

for(reg i=1;i<=n;++i)cout/

divi(

1,n);

printf(

"%lld

",ans);

return0;

}}intmain()

/*author: *miracle*

date: 2018/11/15 10:51:22

*/

更優秀地,可以用單調棧做;

從頂到底,高度單調遞減,高度即位置與當前i之間的height取min

維護這個矩形集合的面積。

遇到hei[i]stack中每個元素維護w和h,表示矩形寬和高。

全域性陣列now維護面積

s1,s2在前分別做一遍

#include#define reg register int

#define il inline

#define numb (ch^'0')

using

namespace

std;

typedef

long

long

ll;il

void rd(int &x)

namespace

miracle;

po(int a,int

b)}sta[

2*n];

inttop;

void

getsa()

if(num==n) break

; m=num;

} }void

gethei()

}ll ans;

ll now;

int be[2*n];

int sum1[2*n],sum2[2*n];

intmain()

else

}else

}sta[++top]=po(be[i-1]==1

,hei[i]);

now+=(be[i-1]==1)*hei[i];

if(be[i]==2) ans+=now;

//cout<

top=0

; now=0

;

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

else

}else

}sta[++top]=po(be[i-1]==2

,hei[i]);

now+=(be[i-1]==2)*hei[i];

if(be[i]==1) ans+=now;

}printf(

"%lld

",ans);

return0;

}}intmain()

/*author: *miracle*

date: 2018/11/15 10:51:22

*/

HAOI2016 找相同字元

其實這道題跟 ahoi2013 差異很像 其實這個問題的本質就是讓你算所有字尾的 lcp 長度之和,但是得來自兩個不同的字串 先把兩個字串拼起來做一遍 sa 由於我們多算了來自於同乙個串內的情況 於是在分別對這兩個串建 sa 減掉這兩次算出來的答案 現在的問題轉化為求出 height 陣列所有子區間...

HAOI 2016 找相同字元

題目鏈結 演算法 首先 子串是字尾的字首 考慮拼接兩個字串 中間用不可見字元隔開 求出該字串的字尾陣列 那麼字首相同的字尾一定排名一定接近 而我們又知道lcp i j min 維護乙個單調遞增的字尾陣列即可 時間複雜度 o nlogn n a b includeusing namespace std...

HAOI2016 找相同字元 SAM

給乙個串建立sam,另乙個在sam上跑匹配,同時計算當前匹配串的所有字尾所產生的的貢獻。由於sam上乙個節點可能不包含所有字尾,要把fat he rfather father 的貢獻下放到son sonso n。詳情見 include include include include include ...