原創做品,轉載請註明出處: 點我
1 #ifndef __KMP__H__ 2 #define __KMP__H__ 3 #include <string> 4 #include <vector> 5 using namespace std; 6 7 class KMP{ 8 public: 9 //void static getNext(const string &str,vector<int> &vec); 10 int kmp(); 11 KMP(){} 12 KMP( const string &target,const string &pattern):mTarget(target),mPattern(pattern){} 13 void setTarget(const string &target); 14 void setPattern(const string &pattern); 15 private: 16 vector< int> mVec; 17 string mTarget; 18 string mPattern; 19 void getNext(); 20 }; 21 #endif
下面是源代碼實現html
1 #include "KMP.h" 2 #include <iostream> 3 #include <vector> 4 using namespace std; 5 6 7 //獲取字符串str的全部子串中相同子集的長度 8 //好比字符串ababacb,分別獲取字符串a,ab,aba,abab,ababa,ababac,ababacb中D 9 //最前面和最後面相同的子串的最大長度,好比 10 //a:由於aa爲a單個字符,因此最前面和最後面相同的子串的最大長度爲a0 11 //aba,最前面一個a和最後面一個元a素a相同,因此值爲a1,abab最前面2個ab和最後面兩個ab相同,值爲a2 12 //ababa最前面3個爲aaba,最後面3個爲aaba,因此值爲a3 13 void KMP::getNext() 14 { 15 mVec.clear(); //清空?ec 16 //vec.push_back(0);//爲a了使用方便,vec的第一個數據不用 17 mVec.push_back(0); //第一個字符的下一個位置必定是0,好比"ababacb",首字符a的值爲0 18 string::const_iterator start = mPattern.begin(); 19 string::const_iterator pos = start + 1; 20 while(pos != mPattern.end()) 21 { 22 string subStr(start,pos+1); //獲取子字符串 23 int strLen = subStr.size() - 1;//獲取子串中D先後相同的子子串的最大長度 24 do 25 { 26 string prefix(subStr,0,strLen); //獲取subStr中D的前面strLen子集 27 string postfix(subStr,subStr.size()-strLen,strLen); //獲取subStr中D的前面?trLen子集 28 if(prefix == postfix) 29 { 30 mVec.push_back(strLen); 31 break; 32 } 33 --strLen; 34 /若是先後相同的子集的長度小於一 35 /說明沒有相同的,則把0壓棧 36 if(strLen < 1) 37 mVec.push_back(0); 38 } while(strLen > 0); 39 40 ++pos; 41 } 42 } 43 44 void KMP::setPattern(const string &pattern) 45 { 46 mPattern = pattern; 47 } 48 49 void KMP::setTarget(const string &target) 50 { 51 mTarget = target; 52 } 53 54 55 56 57 int KMP::kmp() 58 { 59 getNext(); //首先獲取next數據 60 int targetIndex = 0; 61 int patternIndex = 0; 62 int headIndex = 0;//指向跟pattern匹配的Target的第一個元素的索引 63 while(patternIndex != mPattern.size() && targetIndex != mTarget.size()) 64 { 65 for(int i = 0; i < mPattern.size()-1;++i) 66 { 67 if(mPattern[patternIndex] == mTarget[targetIndex]) 68 { 69 ++patternIndex; 70 ++targetIndex; 71 if(mPattern.size()== patternIndex)//若是已經匹配成功,則退出循環 72 break; 73 } 74 else 75 { 76 if(0 == patternIndex)//若是第一個字符就不匹配,則把mTarget左移一位 77 ++headIndex; 78 else 79 { 80 headIndex += patternIndex - mVec[patternIndex-1];//因爲vector索引從零開始,因此要減去一 81 patternIndex = mVec[patternIndex-1];//更新patternIndex索引 82 } 83 targetIndex = headIndex + patternIndex;//跟新targetIndex索引 84 break; 85 } 86 87 } 88 } 89 90 return headIndex; 91 }