KMP算法的C++实现代码时间:2021-10-07 22:49:57/* KMP算法是一种改进的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J.H.Morris同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法). KMP算法的关键是根据给定的模式串W1,m,定义一个next函数,next函数包含了模式串本身局部匹配的信息. */ #include <iostream> #include <vector> #include <functional> #include <algorithm> using namespace std; template<typename FType, typename SType> struct equal_cmp { bool operator ()(const FType& _F, const SType& _S)const { return _F == _S; } }; template<typename RandAccessConcept, typename EqualCmp> inline void CalFailFunction(const RandAccessConcept& in, int len, vector<int>& ff, EqualCmp cmp ) { ff.clear(); ff.reserve(len); ff.push_back(-1); for (int curr = 1, k = -1; curr < len; ++curr) { for (;k >= 0 && !cmp(in[k+1], in[curr]); k = ff[k]); if (cmp(in[k+1], in[curr])) ++k; ff.push_back(k); } } template<typename FRandAccessConcept, typename SRandAccessConcept, typename EqualCmp> inline int KMPSearchFirst(const FRandAccessConcept& d, int dlength, const SRandAccessConcept& p, int plength, EqualCmp cmp, int start = 0) { vector<int> ff; CalFailFunction(p, plength, ff, cmp); for (int i = start, j = -1; i < dlength; ++i) { while (j >= 0 && !cmp(d[i], p[j+1])) j = ff[j]; if (cmp(d[i], p[j+1])) ++j; if (j == plength - 1) return i - plength + 1; } return -1; } template<typename FRandAccessConcept, typename SRandAccessConcept, typename EqualCmp> inline int KMPSearchALL(const FRandAccessConcept& d, int dlength, const SRandAccessConcept& p, int plength, vector<int>& result, EqualCmp cmp) { vector<int> ff; CalFailFunction(p, plength, ff, cmp); result.clear(); for (int i = 0, j = -1; i < dlength; ++i) { while (j >= 0 && !cmp(d[i], p[j+1])) j = ff[j]; if (cmp(d[i], p[j+1])) ++j; if (j == plength - 1) { result.push_back(i - plength + 1); j = ff[j]; } } return result.size(); } //测试 int main() { int d[] = {1,2,3,1,2,3,1,2}; char p[] = "/1/2/3/1/2"; vector<int> result; int found = KMPSearchALL(d, 8, p, 5, result, equal_cmp<int, char> ()); for (int i = 0; i < found; ++i) { cout << result[i] << " "; } cout << endl; return 0; }