字尾陣列 poj 3693

2021-08-07 02:04:04 字數 1178 閱讀 2213

題目:給出乙個串,求重複次數最多的連續重複子串

列舉長度為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

using namespace std;

const int n=2

*100100;

int cl,rk[n],sa[n],rs[n],y[n],wr[n],h[n],r[n][30];

char c[n];

int minn(int

x,int

y)void get_sa(int

m) ln*=

2,m=p;

}sa[0]=0,rk[0]=0;

}void get_h()

h[1]=0;

}void get_rmq()

}int query_rmq(int i,int j)

int main()}}

if(ans==0) printf("%c\n",c[sa[1]]);

else

}return

0;}

poj3693 字尾陣列

題意 給出一串字元,需要求這串字元中的最長重複子串,要是有多個,輸出字典序最小的.我自己的一些想法 這個思路我一開始倒是沒有看明白,慢慢的編下去,才懂了它到底是如何操作的.其實就是列舉多少個字元會匹配,然後求出它們的height值,再用這個值去除以長度,得到有多少個迴圈.具體看 include in...

POJ 3693 字尾陣列

題意 首先定義了乙個字串的重複度。即乙個字串由乙個子串重複k次構成。那麼最大的k即是該字串的重複度。現在給定乙個長度為n的字串,求最大重複次數的子串,有多解時輸出字典序最小解。思路 與spoj的題意差不多,可以點選這裡看 說下字典序的問題,想記錄size 最大重複次數,把所有滿足條件的長度l都記錄起...

poj 3693 字尾陣列 RMQ

這道題是字尾陣列的乙個典型應用。求乙個串中連續重複次數最多的乙個子串。做這道題的時候要把握住,連續重複 和 次數最多這兩個關鍵,才能有突破。下面的思路是照搬大牛的 大神不要打我 在字尾陣列神文中有這題的題解。比較容易理解的部分就是列舉長度為l,然後看長度為l的字串最多連續出現幾次。既然長度為l的串重...