KMP算法C++代码

本文提供了C++实现KMP算法的代码示例,包括KMPSearchFirst和KMPSearchALL两个函数,用于查找字符串中目标子串首次出现的位置和所有出现的位置。代码中包含了fail函数的计算以及主函数中的测试例子。
摘要由CSDN通过智能技术生成
  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;
	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();
}


  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值