上邊寫了個大致思路,然後看了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...