KMP算法C++代码

时间:2021-01-20 19:59:21
  1. //by baihacker 
  2. #include <iostream>  
  3. #include <vector>  
  4. #include <functional>  
  5. #include <algorithm>  
  6. using namespace std;
  7. template<typename FType, typename SType>
  8. struct equal_cmp
  9. {
  10.   bool operator ()(const FType& _F, const SType& _S)const
  11.   {return _F == _S;}  
  12. };  
  13. template<typename RandAccessConcept,
  14.          typename EqualCmp>
  15. inline void     
  16. CalFailFunction(
  17.                 const RandAccessConcept& in,
  18.                 int len,
  19.                 vector<int>& ff,
  20.                 EqualCmp cmp
  21.                 )
  22.     ff.clear();
  23.     ff.reserve(len);
  24.     ff.push_back(-1);
  25.     for (int curr = 1, k = -1; curr < len; ++curr)
  26.     {
  27.         for (;k >= 0 && !cmp(in[k+1], in[curr]);
  28.                 k = ff[k]);
  29.         if (cmp(in[k+1], in[curr])) ++k;
  30.         ff.push_back(k);
  31.     }   
  32. }  
  33. template<typename FRandAccessConcept,
  34.          typename SRandAccessConcept,
  35.          typename  EqualCmp>
  36. inline int      
  37. KMPSearchFirst(
  38.                 const FRandAccessConcept& d,
  39.                 int   dlength,
  40.                 const SRandAccessConcept& p,
  41.                 int   plength,
  42.                 EqualCmp cmp,
  43.                 int start = 0
  44.                 )
  45. {
  46.     vector<int> ff;
  47.     CalFailFunction(p, plength, ff, cmp);
  48.     for (int i = start, j = -1; i < dlength; ++i)
  49.     {
  50.         while (j >= 0 && !cmp(d[i], p[j+1])) j = ff[j];
  51.         if (cmp(d[i], p[j+1])) ++j;
  52.         if (j == plength - 1) return i - plength + 1;
  53.     }
  54.     return -1; 
  55. }    
  56. template<typename FRandAccessConcept,
  57.          typename SRandAccessConcept,
  58.          typename EqualCmp>
  59. inline int      
  60. KMPSearchALL(
  61.                 const FRandAccessConcept& d,
  62.                 int   dlength,
  63.                 const SRandAccessConcept& p,
  64.                 int   plength,
  65.                 vector<int>& result,
  66.                 EqualCmp cmp
  67.                 )
  68. {
  69.     vector<int> ff;
  70.     CalFailFunction(p, plength, ff, cmp);
  71.     result.clear();
  72.     for (int i = 0, j = -1; i < dlength; ++i)
  73.     {
  74.         while (j >= 0 && !cmp(d[i], p[j+1])) j = ff[j];
  75.         if (cmp(d[i], p[j+1])) ++j;
  76.         if (j == plength - 1)
  77.         {
  78.              result.push_back(i - plength + 1);
  79.              j = ff[j];
  80.         }    
  81.     }
  82.     return result.size();
  83. }      
  84. int main()
  85. {
  86.     int d[] = {1,2,3,1,2,3,1,2};
  87.     char p[] = "/1/2/3/1/2";
  88.     vector<int> result;
  89.     int found = KMPSearchALL(d, 8, p, 5, result, equal_cmp<intchar>());
  90.     
  91.     for (int i = 0; i < found; ++i)
  92.         cout << result[i] << " ";
  93.     cout << endl;
  94.     
  95.     return 0;
  96. }
       

 2013/06/29 : 更新一些能直接使用并用于较短模式串的代码。推荐一本叫《柔性字符串匹配》的书

template<typename ElemType>
int MatchSO(ElemType* t, int n, ElemType* p, int m, vector<int>& result)
{
typedef unsigned long long NumberType;
const int CharSet = 128;
NumberTypeB[CharSet];
NumberTypeD = ~0;
NumberTypeCheck = 1 << (m-1);
NumberTypeBIT = 1;
for (int i = 0; i < CharSet; ++i) B[i] = ~0;
for (int i = 0; i < m; ++i, BIT <<= 1) B[p[i]] &= ~BIT;
result.clear();
for (int i = 0; i < n; ++i)
{
D = (D << 1) | B[t[i]];
if ((D & Check) == 0) result.push_back(i-m+1);
}
return result.size();
}

template<typename ElemType>
int MatchSA(ElemType* t, int n, ElemType* p, int m, vector<int>& result)
{
typedef unsigned long long NumberType;
const int CharSet = 128;
NumberTypeB[CharSet];
NumberTypeD = 0;
NumberTypeCheck = 1 << (m-1);
NumberTypeBIT = 1;
for (int i = 0; i < CharSet; ++i) B[i] = 0;
for (int i = 0; i < m; ++i, BIT <<= 1) B[p[i]] |= BIT;
result.clear();
for (int i = 0; i < n; ++i)
{
D = ((D << 1) | 1) & B[t[i]];
if ((D & Check) != 0) result.push_back(i-m+1);
}
return result.size();
}

template<typename ElemType>
int MatchKMP(ElemType* t, int n, ElemType* p, int m, vector<int>& result)
{
int* Prefix = new int[m];
{
Prefix[0] = -1;
for (int i = 1, F = -1; i < m; ++i)
{
while (F >= 0 && p[F+1] != p[i]) F = Prefix[F];
if (p[F+1] == p[i]) ++F;
Prefix[i] = F;
}
}
{
result.clear();
for (int i = 0, F = -1; i < n; ++i)
{
while (F >= 0 && p[F+1] != t[i]) F = Prefix[F];
if (p[F+1] == t[i]) ++F;
if (F+1 == m)
{
result.push_back(i-m+1);
F = Prefix[F];
}
}
}
delete[] Prefix;
return result.size();
}