題目傳送門
簡單講解一下題意:
給出乙個字串,求最長至少出現了 \(k\) 的子串(可重疊)。
這題需要我們在乙個模式串中找相同的子串,很容易就能想到字尾陣列。
那麼,如何找至少重複出現 \(k\) 次的子串呢?
考慮二分子串的長度,看看答案是否具有單調性。
如果長度為 \(len\) 的子串出現了 \(k\) 次,那麼一定有長度小於 \(len\) 的子串出現了 \(k\) 次(這些子串可以是長度為 \(len\) 的子串的子串)
這樣題目就變成了判定性問題,我們只需判斷是否有長度為 \(len\) 子串出現次數\(\geqslant k\)
問題又來了,如何判斷字串中是否有至少重複出現 \(k\) 次的子串呢?
要找重複 \(k\) 次的子串,其實就是找 \(k\) 個相同的子串。找相同的子串,可以考慮使用字尾陣列。對於得到的 \(height[~]\) 陣列,使用分組的方法,使得每組中的每個字尾的最長公共字首都 \(\geqslant len\) ,再判斷是否有一組中的字尾數量 \(\geqslant k\) 即可。
時間複雜度:\(\theta(n\log_2)\)
二分答案不必講,求字尾陣列和 \(height[~]\) 陣列可以參考**或者學習總結-字尾陣列
然後...就沒有然後了,直接上**:
#includeusing namespace std;
const int maxn = 1000005;
int sa[maxn], rak[maxn], sum[maxn], height[maxn];
int key2[maxn], newrak[maxn], a[maxn];
int n, k, m;
bool cmp(int a, int b, int l)
void getheight()
int j = sa[rak[i]-1];
while(a[i+k] == a[j+k]) k++;
height[rak[i]] = k;
if(k != 0) k--;
}}bool ok(int x)
return false;
}int main()
getheight();
int l = 0, r = n+1;
while(l+1 < r)
printf("%d", l);
return 0;
}
USACO06DEC 牛奶模式
題意 求最長的可重疊的 k重複子串 的長度 考慮二分長度s,轉化為驗證性問題。對sa進行分組。保證組內height最小為s。這樣在組內rmq就可以任意了,因為rmq一定是大於s的。只要組內元素個數大於等於k就是可行解。1 include 2 using namespace std 34 struct...
USACO混合牛奶
題目 問題 a 混合牛奶 時間限制 1 sec 記憶體限制 128 mb 提交 39 解決 25 提交 狀態 討論版 命題人 201805050252 題目描述 牛奶包裝是乙個如此低利潤的生意,所以盡可能低的控制初級產品 牛奶 的 變的十分重要。請幫助快樂的牛奶製造者 merry milk make...
Mixing Milk 混合牛奶 USACO
mixing milk 混合牛奶 牛奶包裝是乙個如此低利潤的生意,所以盡可能低的控制初級產品 牛奶 的 變的十分重要.請幫助快樂的牛奶製造者 merry milk makers 以可能的最廉價的方式取得他們所需的牛奶.快樂的牛奶製造公司從一些農民那購買牛奶,每個農民賣給牛奶製造公司的 不一定相同.而...