深入串的模式匹配算法(普通算法和KMP算法)的详解

 更新时间:2013年05月29日 09:19:02   作者:  
本篇文章是对串的模式匹配算法(普通算法和KMP算法)的应用进行了详细的分析介绍,需要的朋友参考下
串的定位操作通常称作串的模式匹配,是各种处理系统中的最重要操作之一。
模式匹配最朴素的算法是回溯法,即模式串跟主串一个字符一个字符的匹配,当模式串中跟主串不匹配时,主串回溯到与模式串匹配开始的下一个位置,模式串回溯到第一个位置,继续匹配。算法的时间复杂度为O(m*n),算法如下:
复制代码 代码如下:

//朴素的串的模式匹配算法,S为主串,T为模式串,即找S中有没有与T相同的字串
int Index(char *S, char *T, int pos)//pos记录从哪一位开始匹配可以直接用0代替
{
 int i=pos, j=0;
 while(i <strlen(S) && j <strlen(T))//确保未超出字符串的长度
 {
  if (S[i] == T[j])
      { ++i; ++j;} //如果相同,则继续向后比较
  else
      {i = i-j+1; j =0;} //如果不同,就回溯,重新查找
 }
 if (j == strlen(T))
  return i-strlen(T); //若匹配成功,返回S中与T字符串相同开始位置的索引
 else return 0; //若匹配不成功,返回0
}

O(m*n)的时间复杂度有点大,于是人们发现了KMP算法,核心思想是:当不匹配发生时,主串不回溯,模式串回溯到“合适”的位置,哪个位置合适,只与模式串有关,所以可以先算出模式串中各个字符,当不匹配发生是,应该回溯到哪个位置。算法整体时间复杂度O(m+m)。
算法如下:
复制代码 代码如下:

void GetNext(char* T, int *next)
{
 int i=1,j=0;
 next[1]=0;
 while( i < strlen(T) )
 {
  if (j == 0 || T[i] == T[j])
  {
    ++i; ++j;
    next[i] = j;
  }
  else j = next[j];
 }
}
int KMP(char* S, char* T, int pos)
{
 int i = pos, j = 1;
 while (i)
 {
  if (S[i] == T[j])
  {
   ++ i;  ++ j;
  }
  else
   j = next[j];
 }
 if (j > strlen(T))
  return i-T[0];
 else
  return 0;
}

求next的操作不是最优的,因为他没有考虑aaaaaaaaaaaaaaaaaaab的情况,这样前面会出现大量的1,这样的算法复杂度已经和最初的朴素算法没有区别了。所以稍微改动一下:
复制代码 代码如下:

void GetNextEx(char *T, int *next)
{
 int i=1,j=0; next[1] = 0;
 while(i < strlen(T))
 {
  if (j == 0 || T[i] == T[j])
  {
   ++i; ++j;
   if (T[i] == T[j])
    next[i] = next[j];  //减少回退次数
   else   next[i] = j;  //和上面算法一样next[i]=j
  }
  else j = next[j];
 }
}

相关文章

  • VC6.0打开文件以及向工程中添加文件时程序崩溃自动退出解决方法

    VC6.0打开文件以及向工程中添加文件时程序崩溃自动退出解决方法

    vc6.0程序中,点击打开文件以及向工程中添加文件时,程序竟然崩溃自动退出了,不知什么原因,安装相同的vc程序,本本竟然出现此缘故
    2013-01-01
  • c语言执行Hello World背后经历的步骤

    c语言执行Hello World背后经历的步骤

    这篇文章介绍了c语言执行Hello World背后经历的步骤,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-12-12
  • c++ decltype关键字的用法

    c++ decltype关键字的用法

    这篇文章主要介绍了c++ decltype关键字的用法,帮助大家更好的理解和学习c++,感兴趣的朋友可以了解下
    2020-10-10
  • C语言递归应用实现扫雷游戏

    C语言递归应用实现扫雷游戏

    这篇文章主要为大家详细介绍了C语言递归应用实现扫雷游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • C++面试题之进制转换的实例

    C++面试题之进制转换的实例

    这篇文章主要介绍了C++面试题之进制转换的实例的相关资料,希望通过本文能帮助到大家,让大家理解掌握这样的知识,需要的朋友可以参考下
    2017-10-10
  • C语言数组a和&a的区别讲解

    C语言数组a和&a的区别讲解

    今天小编就为大家分享一篇关于C语言数组a和&a的区别讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-02-02
  • C语言举例讲解i++与++i之间的区别

    C语言举例讲解i++与++i之间的区别

    这篇文章主要介绍了C语言中i++和++i的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05
  • C++输入输出重定向方法示例

    C++输入输出重定向方法示例

    这篇文章主要给大家介绍了关于C++输入输出重定向的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-09-09
  • linux c++ 服务器端开发面试必看书籍整理

    linux c++ 服务器端开发面试必看书籍整理

    这篇文章主要介绍了linux c++ 服务器端开发面试必看书籍整理,需要的朋友可以参考下
    2020-02-02
  • C语言字符串与字符数组面试题中最易错考点详解

    C语言字符串与字符数组面试题中最易错考点详解

    这篇文章主要介绍了C语言字符串与字符数组面试题中最易错考点,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-09-09

最新评论