字符串匹配的KMP算法实现

本文介绍了一种使用KMP算法来解决字符串中模式串出现次数的问题。通过两次运用KMP算法,先计算模式串的next数组,再用此数组在源字符串中查找模式串,实现了高效匹配。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题源自数据结构书。

 

 问题:字符串src中含有模式串pat的个数

举例:src= 00000111111111101010111010101001

pat=110

src中含有多少个pat?

 

分析:

没有回溯的KMP算法。

1)首先实现一个next[]数字,其中的值,是匹配失误之后的下一次匹配的位置。next[0]=-1; next[1]=0;后面的多数都不是0。这个实际是一个KMP的匹配过程;

2)然后把pat在src中进行匹配,又是一个KMP的匹配过程。

 

代码:

  1. const int pat_length = 3;
  2. int src_length = 0;
  3. // 计算next[],一次KMP算法
  4. bool nextPos(const char* pPat, int* next)
  5. {
  6.     int k = -1;
  7.     next[0] = k;
  8.     
  9.     int index = 0;
  10.     do {
  11.         if ( (-1 == k) || pPat[index] == pPat[k] )
  12.         {
  13.             k++;
  14.             index++;
  15.             next[index] = k;
  16.         }
  17.         else
  18.         {
  19.             k = next[k];
  20.         }
  21.     }  while ( index < pat_length - 1 );
  22.     return true;
  23. }
  24. // pat与src进行匹配,一次KMP算法
  25. int match(const char* pSrc, const char* pPat, const int* next)
  26. {
  27.     int times = 0;
  28.     
  29.     int srcIndex = 0;
  30.     int patIndex = 0;
  31.     
  32.     while ( patIndex < pat_length && srcIndex < src_length )
  33.     {
  34.         if ( patIndex == -1 || pSrc[srcIndex] == pPat[patIndex] )
  35.         {
  36.             patIndex++;
  37.             srcIndex++;
  38.         }
  39.         else
  40.         {
  41.             patIndex = next[patIndex];
  42.         }
  43.         
  44.         if ( patIndex == pat_length )   //match
  45.         {
  46.             times++;
  47.             patIndex = 0;
  48.         }
  49.     }    
  50.     return times;
  51. }
  52. //测试程序
  53. int main(int argc, char* argv[])
  54. {
  55.     using namespace std;    
  56.     char src[] = "acabaabaabcacaabc";
  57.     char pat[] = "abaabcac";
  58.     src_length = sizeof(src);
  59.     int  next[pat_length];
  60.     int times = 0;
  61.     if ( nextPos(pat, next) )
  62.     {
  63.         times = match(src, pat, next);
  64.         cout << "times:" << times << endl;
  65.     }
  66.     
  67.     getchar();
  68.     return 0;
  69. }
编写一个kmp.cpp,实现顺序串的kmp算法: ```cpp #include <iostream> #include <cstring> using namespace std; void getNext(const char *pattern, int *next) { int len = strlen(pattern); next[0] = -1; int i = 0, j = -1; while (i < len) { if (j == -1 || pattern[i] == pattern[j]) { ++i; ++j; next[i] = j; } else { j = next[j]; } } } int kmpSearch(const char *text, const char *pattern) { int len1 = strlen(text); int len2 = strlen(pattern); int *next = new int[len2]; getNext(pattern, next); int i = 0, j = 0; while (i < len1 && j < len2) { if (j == -1 || text[i] == pattern[j]) { ++i; ++j; } else { j = next[j]; } } delete[] next; if (j == len2) { return i - j; } else { return -1; } } int main() { const char *text = "ababcabcacbab"; const char *pattern = "abcac"; int index = kmpSearch(text, pattern); if (index != -1) { cout << "Pattern found at index " << index << endl; } else { cout << "Pattern not found!" << endl; } return 0; } ``` 编写sqstring.cpp,定义顺序串的结构,并实现顺序串: ```cpp #include <iostream> using namespace std; const int MAX_SIZE = 10001; struct SqString { char data[MAX_SIZE]; int length; }; void initSqString(SqString &str, const char *text) { int len = strlen(text); for (int i = 0; i < len; ++i) { str.data[i] = text[i]; } str.length = len; } void printSqString(const SqString &str) { for (int i = 0; i < str.length; ++i) { cout << str.data[i]; } cout << endl; } int main() { SqString str; const char *text = "Hello, world!"; initSqString(str, text); printSqString(str); return 0; } ``` 使用g++编译上述两个文件: ``` g++ kmp.cpp -o kmp g++ sqstring.cpp -o sqstring ``` 运行kmp程序,输出为: ``` Pattern found at index 6 ``` 运行sqstring程序,输出为: ``` Hello, world! ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值