朴素字符串匹配算法

性能如下:

最优时间复杂度

\(O(m)\)

最坏时间复杂度

\(O(m\times n)\)

平均时间复杂度

\(O(m\times n)\)

字符串匹配最简单的算法就是朴素字符串匹配算法,其过程如下:

  • 主串和子串匹配时, \(i,j\) 指针同时进一

  • 主传和子串失配时, \(i=i-j+1, j=0\)

在字符串匹配过程中,由于子串的失配。主传指针 \(i\) 持续向前回溯,其简单实现如下:

int strMatch(const char *mainStr, const char *subStr) {
// 计算主串长度
int mainLen = strlen(mainStr);
// 计算子串长度
int subLen = strlen(subStr);

if (subLen > mainLen) return -1;
int i = 0, j = 0;
while (i < mainLen && (j < subLen)) {
   if (mainStr[i] == subStr[j]) {
      // 主串和子串匹配时指针同时向后移一位
      ++i; ++j;
   } else {
      // 主串和子串失配时指针向前回溯
      i=i-j+1; j = 0;
   }
}
if (j == subLen) return i-j;
return -1;
}

根据算法导论,我们可以得到一个更加简要的写法:

bool strCmp(const char* a, size_t aBegin, const char* b, size_t bBegin, size_t len) {
   for(size_t i = 0; i < len; ++i) {
      if(a[aBegin + i] != b[bBegin + i]) return false;
   }
   return true;
}

int NATIVE_STRING_MATCHER(const char* T, const char* P) {
   size_t n = strlen(T) - 1;
   size_t m = strlen(P) - 1;
   for(size_t s = 0; s <= (n - m); ++s) {
      if(strCmp(P, 1, T, s + 1, m)) return (s + 1);
   }
   return -1;
}

算法导论中数组的起始是零

KMP 匹配算法

KMP 算法的性能如下:

平均时间复杂度

\(O(n+m)\)

KMP 算法实现的核心是求解 next 数组,这部分内容相对而言比较简单:

int *CountNext(const char *P) {
   int *next = (int*)malloc(strlen(P) * sizeof(int));
   next[0] = 0;
   int i = 1, j = 0;
   for (int i = 1; i < strlen(P); ++i) {
      if (P[i] == P[j]) {
         // 如果匹配,next[i] = next[i-1]+1
         // 这时候说明 P[0:j] == P [x:i]
         // 这里 x 是将 i 向前推时 next 第一个不为零的位置
         next[i] = next[i - 1] + 1;
         ++j;
      } else {
         // 如果发生失配,就将 j 指针移至开头
         j = 0;
         next[i] = 0;
      }
   }
   return next;
}

KMP 匹配和暴力匹配唯一的区别就是 i 指针不再回溯,只有 j 指针会回溯:

int KMP(const char *T, const char *P) {
   int *next = CountNext(P);
   const int n = strlen(T);
   const int m = strlen(P);
   int i = 0, j = 0;
   for (; i < n && j < m; ++i) {
      if (T[i] == P[j]) ++j;
      else j = next[j];
   }
   if (j == m) return i - j;
   return -1;
}

附记

尽管这里只介绍了暴力匹配和 KMP 匹配算法,但是现实中还有其他比较好的算法,其性能有些甚至要优于 KMP 算法。参见 字符串匹配算法总结

Last moify: 2025-01-27 08:58:24
Build time:2025-07-18 09:41:42
Powered By asphinx