KMP演算法模板 入門習題 AC碼

2021-10-04 17:54:21 字數 3922 閱讀 1481

kmp中最關鍵的就是通過getnext函式得到next陣列。並且getnext函式也有一點點小區別,我想在此一一枚舉出來,作為模板給自己備用。

重點文章:從頭到尾徹底理解kmp(2023年8月22日版)

最近才理解了為什麼單字元無前字尾:字首不包括字串的最後乙個字元,字尾不包括字串的第乙個字元。

模板一:

說明:next[i]儲存的是第i+2個字元失配後要跳轉的位置,其值等於長度為i+1的字串,即p[0]p[1]……p[i]前字尾的最大相同長度。

在kmp函式中的使用,如果p[j]!=s[i],則j=next[j-1]。

這是next陣列中沒有-1元素的情況,適用於一般的模式匹配,不論是字串還是整型陣列。

int next[maxn]

;void

getnext

(char

* p,

int len)

}

模板二:

說明:next[i]儲存的是第i+1個字元即p[i]失配後要回溯的位置,相當於模板一的next陣列右移乙個單位。next[i]值的大小為除去p[i]後的前i個字元組成的字串,即p[0]p[1]……p[i-1]的最大字首字尾的相同字元數。因此,next[len]也是有值的。

同樣是沒有-1存在的情況,在kmp函式中使用時,若p[j]!=s[i],則j=next[j].

理解next[0]==next[1]==0:第1個字元之前無字元,第2個字元之前只有1個字元,兩者情況均無字首字尾,因此預設為0。

int next[maxn]

;void

getfail

(char

* p,

int plen)

}

模板三:

說明:該getnext的函式是經過優化的版本,匹配的速度可以更快一點。在上述兩個模板中沒有優化。

以模板一為例,若有字串"aaabcdaaa",則next[0],next[1],next[2]是依次遞增的,其值分別為0,1,2,如果p[2]=a和s[x]不匹配,則會跳到p[next[2-1]],即p[1],p[1]仍為a,顯然也和s[x]不匹配,依次進行下去會發現到起點p[0]仍不匹配。

因此可以針對這點進行優化來減少幾次迴圈。優化的方式為當p[i]==p[next[i]]時,next[i]=next[next[i]]。詳細分析可以看**部落格。

//優化過後的next 陣列求法

void

getnextval

(char

* p,

int next)

else

}}

對模板一和模板二進行優化,似乎得next陣列完全生成後再進行,如果邊生成邊優化會使陣列出問題。

for

(int i =

1; i <= plen; i++)if

(p[i]

== p[next[i]

])next[i]

= next[next[i]

];

①hdu - 2087 剪花布條

分析:基礎模板題。

#include

#include

using

namespace std;

const

int maxn =

1000+5

;int next[maxn]

, cnt;

void

getfail

(char

* p,

int plen)

}void

kmp(

char

* s,

char

* p)

else

return;}

}}intmain

(void

)return0;

}

②hdu - 1686 oulipo

分析:該題字串匹配成功後回溯的地方應該是next陣列中的對應元素,而非首字元。

#include

#include

using

namespace std;

const

int maxp =

1e4+5;

const

int maxs =

1e6+5;

int next[maxp]

, ans;

char s[maxs]

,p[maxp]

;void

getnext

(int len)

}void

kmp()}

intmain

(void

)return0;

}

③hdu - 1711 number sequence

分析:int陣列的kmp,和char陣列是一樣的。

#include

#include

using

namespace std;

const

int maxp =

1e4+5;

const

int maxs =

1e6+5;

int next[maxp]

, ans;

int s[maxs]

,p[maxp]

;void

getnext

(int len)

}int

kmp(

int s,

int slen,

int p,

int plen)

if(j < plen)

return-2

;else

return i - j;

}int

main

(void

)return0;

}

④poj - 2406 power strings

這種東西還是挺神奇的,感覺和數學定理一樣,雖然正確但是不會證啊,背就完事了。

**如下:

#include

#include

using

namespace std;

const

int maxn =

1e6+5;

int next[maxn]

;char p[maxn]

;void

getnext

(char

* p)

else

k = next[k];}

if(len %

(len - next[len])==

0)printf

("%d\n"

, len /

(len - next[len]))

;else

printf

("1\n");

}int

main

(void

)return0;

}

⑤poj - 1961 period

分析:上一題的加強版,暴力求解是不能過了。如果理解了上一題,這個也是挺容易的。

#include

#include

using

namespace std;

const

int maxn =

1e6+5;

int next[maxn]

;char p[maxn]

;void

getnext

(char

* p)

}int

main

(void

)return0;

}

拓展KMP演算法 入門 模板

擴充套件kmp演算法,圖很形象,寫的也很清晰,下面的模板就是出自該部落格文章。拓展kmp是求母串s長度為n和子串t長度為m,求s的每乙個字尾子串與t的字首子串匹配的最長長度。求解模式串t的next陣列,這個函式和下面的函式幾乎相同 void getnext string t,int m,int ne...

KMP演算法(模板)

time limit 1000ms memory limit 65536k 有疑問?點這裡 給定兩個字串string1和string2,判斷string2是否為string1的子串。輸入包含多組資料,每組測試資料報含兩行,第一行代表string1 長度小於1000000 第二行代表string2 長...

KMP演算法模板

在文字t 1.n 中找到某個模式p 1.m 所有出現的位置被稱作字串匹配問題 m n p3375 模板 kmp字串匹配 這道題在洛谷上的評級居然是普及 普及?qvq 實現起來還是比較簡單的,只不過有很多細節可以有很多種寫法,看別人的 容易凌亂。理解起來比較困難的部分是如何get next 不建議初學...