KMP算法之 模板+個人總結+好題

最後一個月的倔強,希望心想事成。

字符串彙總篇

1. next數組

首先是next數組。kmp的核心無非於next數組:

  1. next[0]=1/0next[0]=-1 / 0
  2. next[i]inext[i]表示模式串的前i個字符的最長公共前後綴的長度
  3. 出現失配的時候,因爲前 j 個字符有 next[j]next[j] 個最長公共前後綴,就說明現在這裏失配了但是前面的有 next[j]next[j] 個字符是不用再次匹配的,所以模式串向右移動 jnext[j]j-next[j] 個單位,即j=next[j]j=next[j]
  4. 值得一提的是:lennnext[n]設len爲n-next[n]
  5. next[n]0nlennnext[n]n/len如果next[n]不爲0且n是len的倍數,那麼該串的最小循環節是n-next[n],且循環次數爲n/len;
  6. 否則該串需添加 len - n%len 個字符才能形成循環串。(n%len在這裏爲串中後綴屬於循環串的一部分)
void getnexts(){
    ll i=0,j=-1;
    nexts[i]=j;
    while(i<m){
        if(j==-1||p[i]==p[j]) nexts[++i]=++j;
        else j=nexts[j];
    }
}

2. kmp匹配過程

如果說next數組的匹配過程是模式串匹配自身,那麼kmp的過程就是模式串匹配文本串。
說實話也就是回溯過程與暴力不一樣而已,但是這就是一個很大的優化點。
匹配結束後,如果j==mj==m說明模式串匹配結束,即在文本串中出現在iji-j的位置上。

ll kmp(){
    getsnexts();
    ll i=0,j=0;
    while(i<n&&j<m){
        if(j==-1||s[i]==p[j]) ++i,++j;
        else j=nexts[j];
    }
    if(j==m) return i-j;
    return -1;
}

3. 有點模板且需要一點思考的題 (適合初學者/複習)

1.next求補齊循環節
運用上述next的內容即可。
2.next求有多少子串爲其原串的前綴
提示:next[i]表示最長公共前後綴,那麼這個後綴長度即爲匹配的前綴。
3.求模式串前綴與文本串後綴的最大匹配
不難想到把文本串皆在模式串後面,但要考慮一下next[m+n]>mnext[n+m]>nnext[m+n]>m||next[n+m]>n的情況。
4.next求循環週期
運用上述next的內容即可。
5.求模式串中 E+A+E+B+E(其中AB爲任意長度的子串) E的最大長度
find的暴力美學。
6.next遍歷求循環節+循環週期
運用上述next的內容即可。
7.next求既是前綴又是後綴的子串長度
運用上述next的內容即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章