日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++ : KMP 字符串匹配算法

發布時間:2024/10/14 c/c++ 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ : KMP 字符串匹配算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在傳統字符串匹配中我們求得字符串p出現在字符串s中的位置。我們把字符串s稱為主串,字符串p稱為模式串。

KMP算法的原理簡單來說就是匹配的時候不回溯主串的指針i,而只回溯模式串指針j ,即匹配過程中,不移動主串,指移動模式串來達到"盡可能向右滑動最大的距離"。

s[num]012345678910111213141516171819202122
主串sacabaabaabcacaabc
模式串pabaabc

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖1.

假如模式串p中的c與s[11] 失配了,那么再傳統匹配算法中,是拿s[7]和p[0] (a)去匹配,而在KMP匹配中是那s[11]和p[2] (a)中去匹配。因為在這次失配中可知,主串s中6~10的值就是abaab,再拿p[0]和s[7] 匹配必定失配,這次比較就顯得多余。那么我們怎么知道失配的時候,模式串要向右移多少個單位呢?

假設圖1此時主串要正在匹配的位置是 i =11 ,而 與 p[j]=='c',即j==5產生了失配,那么j指針要回溯到 某個k,假如=2值時要進行下一步匹配?,那么k值必須滿足兩個關系式

由圖一可知? ?p[3]p[4]=s[9]s[10],

由圖二可知? ?p[0]p[1]=s[9]s[10]

s[num]012345678910111213141516171819202122
主串sacabaabaabcacaabc
模式串paba

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? ?圖2.

換成通用表達式就是

用邏輯意義上來解釋公式3:就是當在模式串匹配第j個要回溯到k時此時j和k滿足 前綴k個值和后綴k個值要相同。滿足這條件的最大k值即為將要回溯的位置,假如用next數組表示模式串要回溯的位置其中 next[j]=k。

所以實際上,模式串中的next[j]的值與主串s是無關的。

假設next[j]=k即求next[j+1]

如果此時P[j] = P[k]? 那么next[j+1]=k+1 即 next[j+1]= next[j] +1

如果此時 P[j] != P[k] ,那么就要移動next[k]個字符進行比較,達到s[i] = p[k],前綴與后綴對齊的目的。相等則next[j+1]=next[k]+1,不相等則迭代 k=next[k]重新移動比較,例如結合圖3和圖4,next[5]=2,求next[6]?

因為next[5]=2,所以比較出P[5] !=P[2],前綴無法對齊后綴就繼續向右移(回溯),

因為next[2]=0,所以比較出P[5] !=p[0],

因為next[0]=-1接下來比對P[5]和P[-1] 因為next[0] = -1;

當不存在可回溯的k時next[j+1] = -1?;

在存在一個可回溯的位置0<k'<k<j 那么?
?

while(k'>0 && k'< k?){if(k' = -1){next[j+1] = 0; }if(p[k'] != p[k]){k= next[k]}else{next[j+1] = next[k] +1 } }
s[num]012345678910111213141516171819202122
主串sacabaabaabcacaabc
模式串pabaabca

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖3

s[num]012345678910111213141516171819202122
主串sacabaabaabcacaabc
模式串pabaabcac

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖4.

.

s[num]012345678910111213141516171819202122
主串sacabaabaabcacaabc
模式串pabaabcac

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?圖5.

.所以字符串abaabcac的next值為 next [] = {-1,0,0,1,1,2,0,1};

改進的next ,

例如字符串 aaaab的next []={-1,0,1,2,3};

s[num]012345678910111213141516171819202122
主串s
模式串paaaab

? ? ? KMP算法中當s[9] 和p[3]? (b)比較失配發生回溯時,接下來s[9] 會和p[2]比較,此時這個比較是多余的必定會再次失配?。把多余的比較剔除掉就是改進的next。

如果回溯的值與原值相等即,? P[j] = P[k]?時直接 另?P[j] = P[next[k]];

hpp:

// // Created by hu on 2020/8/5. //#ifndef SMARTDONGLIB_SSTRING_H #define SMARTDONGLIB_SSTRING_H #include <string> #include <vector>namespace SmartDongLib {class SString {public:SString(){ str_="";}explicit SString(std::string str): str_(std::move(str)){}SString(const SString& str){ str_=str.str_;}int length(){return str_.length();}SString copy(){return *this;};bool isEmpty(){return str_.empty();}void clear(){str_=""; }SString concat(const SString& str2){ SString ret(str_ + str2.str_); return ret;}SString subString(int pos, int len){SString ret (str_.substr(pos, len)); return ret;}SString subString(int pos=0){SString ret (str_.substr(pos)); return ret;}int index( const SString& , int pos =0);int index_KMP(SString& str2, int pos=0);SString replace(SString src, const SString& target);void strinsert(int pos,const SString& T){str_.insert(pos, T.str_);}void strdelete(int pos,int len){str_.erase(pos,len);}SString operator+(std::string str1){ return SString(str_ + std::move(str1));}SString operator+=(std::string str1){ return SString(str_ + std::move(str1));}bool operator==(const std::string& str1){return str_==str1;}std::string get(){return str_;}void getnext(int next[]);private:std::string str_;}; }#endif //SMARTDONGLIB_SSTRING_H

cpp? :

// // Created by hu on 2020/8/5. //#include "sdstructure/linearlist/SString.h" namespace SmartDongLib {inline int SString::index(const SString& str2, int pos ) {int iptr = pos , jptr = 0;while (iptr < str_.length() && jptr<str2.str_.length()){if (str_[iptr] == str2.str_[jptr]){//相等則比較下一位iptr++ ; jptr++;} else{//不相等則回溯,模式串指針從0 開始 i 回溯到原先的起始值+1 , 現值i'與原先的起始值i 滿足 i'-i=j'-j其中j=0iptr = iptr - jptr+1;jptr = 0;}}if (jptr >=str2.str_.length()){return iptr - jptr;}return -1;}/*** <p> 1 . 求next數組,有了next數組后一個一個匹配,如果失配讓 j = next[j];* @param substr* @param pos* @return*/inline int SString::index_KMP(SString& substr, int pos) {int i=pos, j=0;int next[substr.str_.length()];substr.getnext(next);int thisLen=length(),sublen=substr.length();while ( i < thisLen && j < sublen){if (j==-1 || str_[i] == substr.str_[j]){i++;j++;} else{j=next[j];}}if (j >= sublen){int ret =i-sublen;return ret;}return -1;}inline SString SString::replace(SString src, const SString& target) {if (src.str_.empty()){return *this;}int index=0;while ( index != -1) {index = index_KMP(src);if(index != -1) {str_.erase(index, src.str_.length());str_.insert(index, target.str_);}}return *this;}/*** <p>原理: 當求next的第j個元素時,看 j-1 個元素開始和第0個元素比對,k不斷增加取最大值滿足 0<k<j* 從后往前數k個即第 j-k+1...j-1元素與 0...k-1* 如 abaabcac 當(a)j=0 next[0]=0 ; (b)j =1 ,next[1]=1,;(a) j=2時,k=1,第1個元素和第0個元素比對即a和b比不對就是1* 當(a)j=3,k=1,第2個元素和第0個元素 比a和a匹配上了 那就是next[3]=2;* @param substr* @return*/inline void SString::getnext(int next[]) {const int len =str_.length(); // next.resize(len,-1);int i = 0,j=-1;next[0]=-1;while (i<len){if (j==-1 ||str_[i] == str_[j]){++i;++j;next[i]=j;} else{j=next[j];}}//return next;} }

example:

// // Created by hu on 2020/8/6. //#include <iostream> #include "sdstructure/linearlist/SString.cpp" using namespace std; using namespace SmartDongLib; int main(){SString mainstr("acabaabaabcacaabc");SString substr("abaabcac");//-1 0 -1 1 0 2 -1 1SString target("ijn");int next[substr.length()];substr.getnext(next);for (int i :next){cout<<i<<" ";}int index=mainstr.index_KMP(substr);int index2=mainstr.index(substr);cout<<endl<<index;cout<<endl<<index2;mainstr.replace(substr,target);cout<<endl<<mainstr.get(); }

總結

以上是生活随笔為你收集整理的C++ : KMP 字符串匹配算法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。