POJ 3693 (重複次數最多連續重複子串)

2021-08-26 20:48:00 字數 1619 閱讀 9585

上邊寫了個大致思路,然後看了kuangbin的部落格,深入的了解了一下怎麼做。

只是還得注意一些地方:

設目前詢問的長度為k, 則答案顯然為k / l + 1, 但這不一定是最好的。

拿一組例子來說:

xbcabcab

因為要達到n*logn的複雜度,所以外迴圈模擬長度,內迴圈模擬從第幾個位置開始,但每次加的都是l

所以會造成什麼影響呢,看上邊那個字串:

你會發現當l=3的時候  bcabcab  跟  bcab 剛好是裡面最大的一對字尾的公共字首

但你會發現其實當l=3的時候,i根本取不到1。

所以我們考慮k % l的值的意義, 我們可以認為是後面多了k % l個字元, 但是我們更可以想成前面少了(l - k % l)個字元! 所以我

們求得字尾j * l - (l - k % l)與字尾(j + 1) * l - (l - k % l)的最長公共字首。

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

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

#include #include #include #include const int maxn=100010;

const int max_len = 200010;

int r[maxn]; // r 陣列儲存了字串中的每個元素值,除最後乙個元素外,每個元素的值在 1..m 之間,最後乙個元素的值為 0

int wa[maxn], wb[maxn], wv[maxn], ws[maxn]; // 這 4 個陣列是字尾陣列計算時的臨時變數,無實際意義

int sa[maxn]; // sa[i] 儲存第 i 小的字尾在字串中的開始下標,i 取值範圍為 0..n-1

int cmp(int *r, int a, int b, int l)

void da(int *r, int *sa, int n, int m)

return;

}int rank[maxn]; // rank[i] 表示從下標 i 開始的字尾的排名,值為 1..n

int height[maxn]; // 下標範圍為 1..n,height[1] = 0

void calheight(int *r, int *sa, int n)

char str[maxn];

int log[maxn];

int st[30][maxn];

int a[maxn];

void get_rmq(int n)

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

for(int i=1;i<=log[n];i++)else if(step==mmax) a[cnt++]=l;}}

int len=-1,st;

for(int i=1;i<=n&&len==-1;i++)}}

str[st+len*mmax]=0;

printf("case %d: %s\n",icase++,str+st);

}return 0;

}

poj 3693連續重複最多的串

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

字尾陣列 重複次數最多的連續重複子串

poj3693 maximum repetition substring 題意 給定乙個字串,求重複次數最多的連續重複子串。思路 先窮舉長度l,然後求長度為l的子串最多能連續出現幾次。首先連續出現1次是肯定可以的,所以這裡只考慮至少2次的情況。假設在原字串中連續出現2次,記這個子字串為s,那麼s肯定...

求陣列中重複次數最多的元素

例如 陣列a 元素2 3 7 8各出現1次,1出現兩次,5出現4次,則重複次數最多的元素為5.定義乙個陣列int cnt max 將其元素全部初始化為0。然後遍歷陣列a,執行cnt a i 操作。最後在cnt陣列中找最大的數,對應的數即為重複次數最多的數。示例如下 以空間換時間,索引法 int ma...