NOI2016 優秀的拆分 SAM

2021-09-20 15:32:12 字數 1550 閱讀 4291

一類處理字串相交的好東西。

題目就是要對每個位置求一整個位置為結尾/開頭的能寫成ss的串的數量。

除了一些麻煩的演算法以外(比如在sam上啟發式合併之類的),乙個簡單的做法是列舉s的長度,不妨設為d,然後將原串每d個字元切開,發現ss這個串至少碰到兩個縫隙,因此計算相鄰兩段的lcp/lcs就可以知道ss的結尾在某一段中合法的區間,然後用差分維護答案即可。

#include

#define rep(i,a,b) for(int i=a;i<=b;i++)

#define rep(i,v) rep(i,0,(int)v.size()-1)

#define lint long long

#define ull unsigned lint

#define db long double

#define pb push_back

#define mp make_pair

#define fir first

#define sec second

#define gc getchar()

#define debug(x) cerr<<#x<<"="<#define sp <<" "

#define ln typedef pair<

int,

int> pii;

typedef set<

int>

::iterator sit;

inline

intinn()

const

int n=

30010

;int a[n]

,b[n]

;char s[n]

;namespace sam_space

inline

intclear()

inline

intextend

(int w,

int ps)

}return pos[ps]

=las=np,0;

}inline

intmymin

(int x,

int y)

inline

intdfs

(int x)

inline

intbuild()

inline

intgetlca

(int x,

int y)

inline

intquery

(int x,

int y)

}lcs,lcp;

}using sam_space:

:lcs;using sam_space:

:lcp;

inline

intupd

(int

*a,int l,

int r)

inline

intsolve

(int l,

int n)

return0;

}int

main()

return0;

}

NOI2016 優秀的拆分

看到題目,資料範圍有點怪異。對於95 的資料,對於100 的資料,意思是只有5分是正解。好吧,95pts的 很明顯,答案就是 而如何才能拿到100pts呢?我們可以先列舉a段的長度,很明顯每個長度為lcp,與往後求lcs,若 這樣就可以通過 include include include inclu...

NOI2016 優秀的拆分

題目實際上要求我們求從每個點出發的aa串的數量 考慮點i的答案,發現如果字首i與字首j j i 的最長公共字尾 i j,那麼i點出發向前就存在乙個長度為i j的aa串,題目即求對於每個字首,有多少個在他之前的字首滿足條件 考慮字尾自動機,由於每個字首都是字尾自動機parent樹上的一點,即兩個字首的...

NOI2016 優秀的拆分

點此看題 首先轉化問題,我們可以求出a i b i a i b i a i b i 即以i ii結束 開始的aaaa aa串的數量,這樣答案就可以表示為 a i b i 1 sum a i times b i 1 a i b i 1 求這兩個陣列,可以隔距離len lenle n設定乙個點,這樣乙個...