您的位置:首页 > 编程语言 > C语言/C++

KMP算法C++代码

2008-08-20 19:36 204 查看
//by baihacker 

#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;
}

   

 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;
NumberType	B[CharSet];
NumberType	D = ~0;
NumberType	Check = 1 << (m-1);
NumberType	BIT = 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;
NumberType	B[CharSet];
NumberType	D = 0;
NumberType	Check = 1 << (m-1);
NumberType	BIT = 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();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c++ 算法