KMP算法是通过分析模式字符串,预先计算每个位置发生不匹配的时候,所需GOTO的下一个比较位置,整理出来一个next数组,然后在上面的算法中使用。

本全局匹配KMP算法针对串的堆式存储数据结构

  1. # define MAXSIZE 45 //固定next数组的长度
  2.  
  3. # define OK 1
  4. # define ERROR 0
  5.  
  6. typedef int Status; //返回状态
  7.  
  8. //存放匹配字符串的位置
  9. int indexArray[MAXSIZE] = {0};
  10.  
  11. //记录匹配字符串出现的次数
  12. int searchIndex = 0;
  13.  
  14. //------------------串的堆分配存储表示
  15. typedef struct {
  16. char* ch; //指针域,指向存放串值的存储空间基址
  17. int length; // 整型域:存放串长
  18. } HString;

  

next函数值仅取决于模式串本身而和相匹配的主串无关,因此从分析器定义出发而用递推的方法求得next函数的值。

  1. /*
  2. 功能:获取next函数;
  3. */
  4. void get_next(HString* t,int* next)
  5. {
  6.  
  7. int i = 1,j = 0;
  8. *(next+1) = 0;
  9. while(i<t->length)
  10. {
  11. if(j == 0 || *(t->ch+i-1) == *(t->ch+j-1))
  12. {
  13. i++;
  14. j++;
  15. *(next+i) = j;
  16. }
  17. else
  18. j = *(next+j);
  19. }
  20. }

  

匹配过程中产生“失配”时,指针i不变,指针j退回到next[j]所知识的位置上重新经行比较,并且当指针j退至0时,指针id和指针j需同时加1。即若主串中的第i个字符和模式中的第1个字符不等,应从主串中的第i+1个字符起重新匹配。

当所匹配记录相等的字符数大于或等于模式串长度时,记录当前位置,即匹配合适的位置,然后继续进行下一组的匹配。

获取next函数算法的时间复杂度为O(m),通常模式串的长度m比主要串的长度n小得多,因此,对整个匹配算法来说是值得的。

在一般情况下,仅有一次模式匹配的时间复杂度为O(m+n),因此全局模式匹配的时间复杂度与匹配成功次数相关。为O(m+n)*b(b次)。

KMP算法的最大特点就是指示主串的指针不需回溯,整个匹配过程中,对主串仅需从头至尾扫描一编。

  1. /*
  2. 功能:kmp算法 从pos开始,获取串s中所有匹配串t位置,存放在全局函数indexArray中
         初始条件:t非空,且i<=pos<=s->length
  3. */
  4.  
  5. status Index_KMP(HString* s,HString* t,int pos)
  6. {
  7. //处理非法输入
        
  8. if(!t || pos>1 || pos> s->length)
           return ERROR;
  9. //清空
  10. for(int k =0;k<MAXSIZE;k++)
  11. {
  12. indexArray[k] = 0;
  13. }
  14. searchIndex = 0;
  15.  
  16. //得到next数组
  17. int j,next[MAXSIZE] = {};
  18. get_next(s,next);
  19.  
  20. if (pos < 0 || pos > s->length)
  21. exit(0);
  22. int sLength = s->length;
  23. int tLength = t->length;
  24. int i = pos-1;
  25. j = 0;
  26.  
  27. while(i<= sLength && j<=tLength)
  28. {
  29. if(j == 0 ||*(s->ch + i) == *(t->ch + j))
  30. {
  31. ++i;
  32. ++j;
  33. if(j>= tLength)
  34. {
  35. indexArray[searchIndex] = i-tLength+1;
  36. searchIndex++;
  37.  
  38. }
  39. }
  40. else{
  41. j = *(next+j);
  42. }
  43. }
      return OK;
  44. }

  高亮显示区域应为if(j== tLength) 。如果写成大于等于,当主串最后位置出现匹配的字符串,即给下列测试代码中的S1赋值为abaabc时,程序给数值赋值后,i继续自增加,造成最后输出结果为1 9 17 25 26。因此,应将if(j>= tLength)改成if(j== tLength)

测试如下:

  1. HString S1;
  2. InitHString(&S1);
  3. AssigHString(&S1,"abaabc");
  4.  
  5. HString S;
  6. InitHString(&S);
  7. AssigHString(&S,"abaabcd abaabcf abaabcj abaabck");
  8.  
  9. Index_KMP(&S,&S1,1);
  10. printf("S1在S中的出现次数:%d\n",searchIndex );
  11.  
  12. for(int i=0;i<searchIndex;i++)
  13. printf("%d ",indexArray[i]);
  14. printf("\n");

 显示结果为:1 9 17 25 

总结,细心调试,同时要增强代码的健壮性。

全局匹配KMP算法的更多相关文章

  1. 自己对kmp算法的理解,借由 28. 实现 strStr() 为例

    做题思路 or 感想 : 就借由这道题来理解一下kmp算法吧 kmp算法的操作过程我觉得有句话很合适 :KMP 算法永不回退 目标字符串 的指针 i,不走回头路(不会重复扫描 目标字符串),而是借助 ...

  2. 字符串查找算法总结(暴力匹配、KMP 算法、Boyer-Moore 算法和 Sunday 算法)

    字符串匹配是字符串的一种基本操作:给定一个长度为 M 的文本和一个长度为 N 的模式串,在文本中找到一个和该模式相符的子字符串,并返回该字字符串在文本中的位置. KMP 算法,全称是 Knuth-Mo ...

  3. KMP算法匹配原理以及C++实现

    原创作品,转载请注明出处:点我 假设A表示目标字符串,A="abababaababacb",B表示匹配模式,B="ababacb" 用两个指针i和j分别表示,A ...

  4. 【转】字符串匹配的KMP算法:移动位数 = 已匹配 - 部分匹配值(共有长度)

    计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另一个字符串"ABCDABD"? 许多算 ...

  5. 串的匹配:朴素匹配&amp;KMP算法

    引言 字符串的模式匹配是一种经常使用的操作. 模式匹配(pattern matching),简单讲就是在文本(text,或者说母串str)中寻找一给定的模式(pattern).通常文本都非常大.而模式 ...

  6. 从暴力匹配到KMP算法

    前言 现在有两个字符串:\(s1\)和\(s2\),现在要你输出\(s2\)在\(s1\)当中每一次出现的位置,你会怎么做? 暴力匹配算法 基本思路 用两个指针分别指向当前匹配到的位置,并对当前状态进 ...

  7. KMP算法——字符匹配

     暴力匹配: 假设现在我们面临这样一个问题:有一个文本串S,和一个模式串P,现在要查找P在S中的位置,怎么查找呢? 如果用暴力匹配的思路,并假设现在文本串S匹配到 i 位置,模式串P匹配到 j 位置, ...

  8. KMP算法 (字符串的匹配)

    视频参考 对于正常的字符串模式匹配,主串长度为m,子串为n,时间复杂度会到达O(m*n),而如果用KMP算法,复杂度将会减少线型时间O(m+n). 设主串为ptr="ababaaababaa ...

  9. 算法数据结构 | 只要30行代码,实现快速匹配字符串的KMP算法

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是算法数据结构专题的第29篇文章,我们来聊一个新的字符串匹配算法--KMP. KMP这个名字不是视频播放器,更不是看毛片,它其实是由Kn ...

随机推荐

  1. LNMP 参数调优 ( 无注释 )

    简介: PHP FastCGI 优点 1.PHP 脚本运行速度更快.PHP 解释程序被载入内存而不用每次需要时从存储器读取,极大的提升了依靠脚本运行站点的性能. 2.需要使用的系统资源更少.由于服务器 ...

  2. $.getJSON() 回调函数没有执行的原因

    $.getJSON() 方法使用 AJAX 的 HTTP GET 请求获取 JSON 数据. 语法 $.getJSON(url,data,success(data,status,xhr)) url必填 ...

  3. Invalid command 'Header', perhaps misspelled or defined by a module not included in the server configuration

    在Apache的配置文件 httpd.conf 中开启  LoadModule headers_module modules/mod_headers.so  即可解决这个问题.

  4. Java的SSH网站

    1.框架 strusts2 + Hibernate + spring 2.图片 图1-1 网站结构 图1-2 java代码结构 3.源代码 3.1 UserAction.java package co ...

  5. 如何查看Mysql服务器上的版本

    select version(); 1,mysql 的守护进程是mysqld [root@localhost ~]# service mysqld start 启动 MySQL: [确定] 你可以看看 ...

  6. mybatis+oracle如何批量执行多条update

    接口 public void setStatus(List<Columns> columnsList); mapping xmlmapping 中使用foreach,关于标签的使用,资料非 ...

  7. Solidity oraclize解析Json格式数据

    solidity虽然不能解析json数据但是oraclize_query可以直接处理: pragma solidity ^; import "github.com/oraclize/ethe ...

  8. Luogu 2000 拯救世界

    从胡小兔的博客那里过来的,简单记一下生成函数. 生成函数 数列$\{1, 1, 1, 1, \cdots\}$的生成函数是$f(x) = 1 + x + x^2 + x^3 + \cdots$,根据等 ...

  9. code1796 社交网络

    输入描述 Input Description 输入文件中第一行有两个整数,n 和 m,表示社交网络中结点和无向边的数 目.在无向图中,我们将所有结点从 1 到 n 进行编号. 接下来 m 行,每行用三 ...

  10. 3.3.2线程安全的HashMap

    代码:public class SysHashMao { private static Map<String,String> map= Collections.synchronizedMa ...