poj 3693 字尾陣列 RMQ

2021-06-22 22:53:46 字數 1510 閱讀 3842

這道題是字尾陣列的乙個典型應用。求乙個串中連續重複次數最多的乙個子串。做這道題的時候要把握住,連續重複 和 次數最多這兩個關鍵,才能有突破。

下面的思路是照搬大牛的:(大神不要打我

在字尾陣列神文中有這題的題解。

比較容易理解的部分就是列舉長度為l,然後看長度為l的字串最多連續出現幾次。

既然長度為l的串重複出現,那麼str[0],str[l],str[2*l]……中肯定有兩個連續的出現在字串中。

那麼就列舉連續的兩個,然後從這兩個字元前後匹配,看最多能匹配多遠。

即以str[i*l],str[i*l+l]前後匹配,這裡是通過查詢suffix(i*l),suffix(i*l+l)的最長公共字首

通過rank值能找到i*l,與i*l+l的排名,我們要查詢的是這段區間的height的最小值,通過rmq預處理

達到查詢為0(1)的複雜度

,設lcp長度為m, 則答案顯然為m / l + 1, 但這不一定是最好的, 因為答案的首尾不一定再我們列舉的位置上. 我的解決方法是, 我們考慮m % l的值的意義, 我們可以認為是後面多了m % l個字元, 但是我們更可以想成前面少了(l - m % l)個字元! 所以我們求字尾j * l - (l - m % l)與字尾(j + 1) * l - (l - m % l)的最長公共字首。

即把之前的區間字首l-m%l即可。

然後把可能取到最大值的長度l儲存,由於 題目要求字典序最小,通過sa陣列進行列舉,取到的第一組,肯定是字典序最小的。

我的**如下:

#include#include#include#include#include#include#define maxd 100010

#define maxl 300

using namespace std;

int r[maxd], rank[maxd], height[maxd];

int sa[maxd], wa[maxd], wb[maxd], ws[maxl], wv[maxd]; //ws 的大小是最大字元的大小。其他的是串長大小

//r陣列存放字元的值

int cmp(int *p, int x, int y, int l)

void da(int n, int m) //n為字串長度,m為字元的最大值

}void calheight(int n) //n為串的長度減一

/*****************以上都是字尾陣列模板,下面的是具體問題的處理。******************/

char str[maxd];

int dp[maxd][20];

int cnt=0,maxtime=0;

void rmq(int n)

else if(time==maxtime)}}

if(cnt==0||maxtime==1)

int start=0,len=-1;

for(i=1;i=a[j]*(maxtime-1))}}

for(i=start;i

poj3693 字尾陣列 RMQ

感覺思路還是非常神奇的。另外注意一下strlen好像是個on的函式。日狗。tle了乙個晚上。include include include includeusing namespace std define maxn 100005 define forup i,a,b for int i a i b...

POJ 3693 字尾陣列 RMQ

點選開啟鏈結 題意 問連續重複部分最多的串是什麼,不能重疊,且我們要字典序最小的串如xbcabcab,有bcabca重複次數為2,cabcab重複次數也為2,那麼要前邊那個 思路 以前寫過乙個類似的,spoj 687,這個只是求連續重複部分最多的串的次數,並不需要將按字典序最小串輸出,那麼我們可以用...

字尾陣列 poj 3693

題目 給出乙個串,求重複次數最多的連續重複子串 列舉長度為l,然後看長度為l的字串最多連續出現幾次。既然長度為l的串重複出現,那麼str 0 str l str 2 l 中肯定有兩個連續的出現在字串中。那麼就列舉連續的兩個,然後從這兩個字元前後匹配,看最多能匹配多遠。即以str i l str i ...