CH1809 匹配統計 題解

2022-07-31 06:45:10 字數 1258 閱讀 6705

看了好久才懂,我好菜啊……

題意:給兩個字串 \(a\) 與 \(b\),對於 \(q\) 次詢問,每次詢問給出乙個 \(x\),求存在多少個位置使得 \(a\) 從該位置開始的字尾子串與 \(b\) 匹配的長度恰好為 \(x\)。

這題可以 hash+二分 \(o(n\log n)\) 過,還有乙個高階做法是擴充套件 kmp(然而並不會

正解的話,還是 kmp。但此題對 kmp 的理解還是要求很高啊。

對 \(b\) 求一遍 \(nxt\),再求 \(a\) 的 \(f\)。那麼根據定義,\(f_i=j\) 表示 \(a_=b_\),換句話說,\(a\) 從 \(i-j+1\) 開始的字尾與 \(b\) 的匹配長度至少為 \(j\)。

由於我們只是求出了至少,但題目問的是精確值,那麼做乙個轉換,開乙個桶 \(cnt\),\(cnt_i\) 表示匹配長度至少為 \(i\) 的位置有幾個,那麼對於每乙個詢問,答案就是 \(cnt_x-cnt_\)。

求完 \(f\) 後,我們把它扔進桶裡。

還沒完,考慮一下到現在為止 \(cnt\) 裡存了什麼,我們發現現在的 \(cnt_i\) 存的位置個數並沒有覆蓋所有的情況,也就是說我們要做乙個字尾和來覆蓋這些情況。

如何做字尾和?根據 kmp 的性質,如果 \(a[i-j+1\sim i]=b[1\sim j]\),那麼 \(a[i-j+1\sim i-j+nxt[j]]=b[1\sim nxt[j]]\) 同樣成立,並且中間的都不成立,也就是說,\(nxt[j]\) 是次選項。進一步地,\(nxt[nxt[j]],nxt[nxt[nxt[j]]],...\)都是滿足條件的選項,這樣我們的答案就得到了擴充套件並覆蓋了所有情況。

所以我們倒序列舉 \(m\),字尾和的遞推式就是cnt[nxt[i]]+=cnt[i]

本題真心很難理解(好像字串題就沒有好理解的),一定要多畫圖,把抽象描述形象化。

#include #include using namespace std;

const int n=2e5+5;

int n,m,q,nxt[n],f[n],cnt[n];

char a[n],b[n];

int main()

for(int i=1,j=0;i<=n;++i)

for(int i=1;i<=n;++i) ++cnt[f[i]];

for(int i=m;i;--i) cnt[nxt[i]]+=cnt[i];

while(q--)

return 0;

}

題解 CH1809 匹配統計

首先不難想到字串hash的做法,列舉a中的每個位置,二分匹配長度即可,時間複雜度 o n 很明顯正解應該要用kmp,但對於匹配出的乙個f i 我們只能知道 有一次長度至少為f i 的匹配 同時還可能會漏掉一些匹配位,怎麼辦?基於值域的字首和 即令cnt x 長度至少為x的匹配位的個數,易得答案等於c...

題解 CH1809 匹配統計

首先不難想到字串hash的做法,列舉a中的每個位置,二分匹配長度即可,時間複雜度 o n 很明顯正解應該要用kmp,但對於匹配出的乙個f i 我們只能知道 有一次長度至少為f i 的匹配 同時還可能會漏掉一些匹配位,怎麼辦?基於值域的字首和 即令cnt x 長度至少為x的匹配位的個數,易得答案等於c...

CH1809 匹配統計 KMP

求恰好匹配 x xx 長度比較困難,可以轉為求至少匹配 x xx 長度的位置,再作差。用kmp演算法可以求出每個位置最多匹配的長度,而這個長度其實是 於 nex t i nex t ne xt i next i next next i next i ne xt n ext i 因此對於他們,求至少匹...