算法 KMP算法 参考:http://blog.csdn.net/hackbuteer1/article/details/7319115

KMP算法详解:
  KMP算法之所以叫做KMP算法是因为这个算法是由三个人共同提出来的,就取三个人名字的首字母作为该算法的名字。其实KMP算法与BF算法的区别就在于KMP算法巧妙的消除了指针i的回溯问题,只需确定下次匹配j的位置即可,使得问题的复杂度由O(mn)下降到O(m+n)。
  在KMP算法中,为了确定在匹配不成功时,下次匹配时j的位置,引入了next[]数组,next[j]的值表示P[0...j-1]中最长后缀的长度等于相同字符序列的前缀。
  对于next[]数组的定义如下:
  1) next[j]=-1  j=0
  2) next[j]=max k:0<k<j P[0...k-1]=P[j-k,j-1]
  3) next[j]=0  其他
如:
P      a    b   a    b   a
j       0   1    2   3   4
next -1  0    0   1   2
  即next[j]=k>0时,表示P[0...k-1]=P[j-k,j-1]
  因此KMP算法的思想就是:在匹配过程称,若发生不匹配的情况,如果next[j]>=0,则目标串的指针i不变,将模式串的指针j移动到next[j]的位置继续进行匹配;若next[j]=-1,则将i右移1位,并将j置0,继续进行比较。

  比如说:

  S=xxxababcxxx

  P=ababa

  当比较到,p[4]=a与s不匹配,(从0计数)

  xxxababcxxx   i

  xxxababa       j

c与a不相等,此时传统做法是将j设为0,i=i-3,然后p串第一个a与s串第一个b比较(开始时p串第一个a与s串第一个b之前的a比较);kmp算法则i不变,j设为next[j]=2,此时变为:

xxxababcxxx

xxxxxaba  

  既已经知道了第三个a前面为abab,该串的3长度前缀aba与3长度后缀bab不相等,2长度前缀ab与2长度后缀ab相等,此时next[j]=2,因此直接利用后缀的判断结果,将p右移2位。
代码实现如下:

 1 int KMPMatch(char *s,char *p)
 2 {
 3     int next[100];
 4     int i , j;
 5     i = 0;
 6     j = 0;
 7     getNext(p , next);
 8     while(i < strlen(s))
 9     {
10         if(j == -1 || s[i] == p[j])
11         {
12             i++;
13             j++;
14         }
15         else
16         {
17             j = next[j];       //消除了指针i的回溯
18         }
19         if(j == strlen(p))
20             return i - strlen(p);
21     }
22     return -1;
23 }

  因此KMP算法的关键在于求算next[]数组的值,即求算模式串每个位置处的最长后缀与前缀相同的长度, 而求算next[]数组的值有两种思路,第一种思路是用递推的思想去求算,还有一种就是直接去求解。
   1、按照递推的思想:
  根据定义next[0]=-1,假设next[j]=k, 即P[0...k-1]==P[j-k,j-1]
  1)若P[j]==P[k],则有P[0..k]==P[j-k,j],很显然,next[j+1]=next[j]+1=k+1;
  2)若P[j]!=P[k],则可以把其看做模式匹配的问题,即匹配失败的时候,k值如何移动,显然k=next[k]。
  因此可以这样去实现:

 1 void getNext(char *p,int *next)
 2 {
 3     int j,k;
 4     next[0] = -1;
 5     j = 0;
 6     k = -1;
 7     while(j < strlen(p) - 1)
 8     {
 9         if(k == -1 || p[j] == p[k])    //匹配的情况下,p[j]==p[k]
10         {
11             ++j;
12             ++k;
13             next[j] = k;
14         }
15         else                   //p[j]!=p[k]
16             k = next[k];
17     }
18 }

  对于第一次比较,由于k=-1,因此执行“++j;++k;”操作(之后j=1, k=0),使得“next[j=1]=0;”。

  第二次比较时,如果"p[j=1]==p[k=0]",那么“++j;++k;next[j=2]=k=1;”,比如说aaaaaa,从0计数,那么第2个a前面为第0、1位为aa,后缀与前缀的最大相同长度为1。

  如果"p[j=1]!=p[k=0]",由于k=0,k=next[k=0]=-1,之后k=-1。

  为了找到s串中不止一个p串,则需要做些改动:

void getNext(char *p,int *next)
{
    int j,k;
    next[0] = -1;
    j = 0;
    k = -1;
    while(j < strlen(p))
    {
        if(k == -1 || p[j] == p[k])    //匹配的情况下,p[j]==p[k]
        {
            j++;
            k++;
            next[j] = k;
        }
        else                   //p[j]!=p[k]
            k = next[k];
    }
}

将next数组扩充一位

int KMPMatch(char *s,char *p)
{
    int *next=new int[strlen(p)+1]();
    int i , j;
    i = 0;
    j = 0;
    getNext(p , next);
    while(i < strlen(s))
    {
        if(j == -1 || s[i] == p[j])
        {
            i++;
            j++;
        }
        else
        {
            j = next[j];       //消除了指针i的回溯
        }
        if(j == strlen(p))        {            cout<<i-j<<endl;            j=next[j];
            //return i - strlen(p);        }
    }
    return -1;
}
时间: 2024-09-30 21:09:03

算法 KMP算法 参考:http://blog.csdn.net/hackbuteer1/article/details/7319115的相关文章

图像处理算法2——Otsu最佳阈值分割法http://blog.csdn.net/xiaqunfeng123/article/details/17121195

http://blog.csdn.net/xiaqunfeng123/article/details/17121195Otsu法是1979年由日本大津提出的.该方法在类间方差最大的情况下是最佳的,即统计鉴别分析中所用的度量.Otsu方法有一个重要的特性,就是它完全以在一幅图像的直方图上执行计算为基础,而直方图是很容易得到的一维阵列. 具体的公式推理及公式细节就不说了,详见 Conzalez 那本书,我是第三版的,在P.479——P.482 上面. 给出具体步骤如下: 1.计算输入图像的直方图,并

一致性hash 参考:http://blog.csdn.net/cywosp/article/details/23397179/

hash好坏的四个定义: 平衡性:平衡性是指哈希的结果能够尽可能分布到所有的缓冲中去,这样可以使得所有的缓冲空间都得到利用. 单调性:单调性是指如果已经有一些内容通过哈希分派到了相应的缓冲中,又有新的缓冲加入到系统中.哈希的结果应能够保证原有已分配的内容可以被映射到原有的或者新的缓冲中去,而不会被映射到旧的缓冲集合中的其他缓冲区. 添加节点后,原有的哈希结果要么不迁移,要么迁移到新的节点,不会迁移到旧的节点.以hash后取模方式为例,增加一个节点(槽),有的键可能分配到旧节点里 分散性:在分布式

装载 - POJ分类很好很有层次感 from http://blog.csdn.net/zzycsx/article/details/49103451

from http://blog.csdn.net/zzycsx/article/details/49103451 OJ上的一些水题(可用来练手和增加自信) (poj3299,poj2159,poj2739,poj1083,poj2262,poj1503,poj3006,poj2255,poj3094)初期: 一.基本算法:      (1)枚举. (poj1753,poj2965)      (2)贪心(poj1328,poj2109,poj2586)      (3)递归和分治法.     

RTP协议分析(转自:http://blog.csdn.net/bripengandre/article/details/2238818)

RTP协议分析 第1章.     RTP概述 1.1.  RTP是什么 RTP全名是Real-time Transport Protocol(实时传输协议).它是IETF提出的一个标准,对应的RFC文档为RFC3550(RFC1889为其过期版本).RFC3550不仅定义了RTP,而且定义了配套的相关协议RTCP(Real-time Transport Control Protocol,即实时传输控制协议).RTP用来为IP网上的语音.图像.传真等多种需要实时传输的多媒体数据提供端到端的实时传输

http://blog.csdn.net/LANGXINLEN/article/details/50421988

GitHub上史上最全的Android开源项目分类汇总 今天在看博客的时候,无意中发现了 @Trinea在GitHub上的一个项目 Android开源项目分类汇总, 由于类容太多了,我没有一个个完整地看完,但是里面介绍的开源项目都非常有参考价值,包括很炫的界面特效设计.个性化控件.工具库.优秀的Android 开源项目.开发测试工具.优秀个人和团体等.可以这样说,每一位Andorid开发人员都能从中找到一个或多个适用自己项目的解决方案,消化吸收并加以利 用,可以为自己的APP增色不少.文章最后还

使用C++扩展Python的功能 转自:http://blog.csdn.net/magictong/article/details/8897568#comments

使用C++扩展Python的功能 环境 VS2005Python2.5.4 Windows7(32位) 简介 长话短说,这里说的扩展Python功能与直接用其它语言写一个动态链接库,然后让Python来调用有点不一样(虽然本质是一样的).而是指使用Python本身提供的API,使用C++来对Python进行功能性扩展,可以这样理解,使用更高效的语言实现一些算法计算等等需要更高执行效率的核心(或者需要与系统进行密切交互的)模块,然后让Python像调用内建标准库的方式来调用这些模块,听起来是不是很

推荐一些C#相关的网站、资源和书籍 (转载自http://blog.csdn.net/chinacsharper/article/details/17514923)

一.网站 1.http://msdn.microsoft.com/zh-CN/ 微软的官方网站,C#程序员必去的地方.那里有API开发文档,还有各种代码.资源下载. 2.http://social.msdn.microsoft.com/Forums/zh-CN/home 微软msdn论坛.定位于微软技术的传播和技术问题的解决,是学习微软技术的好去处. 3.http://www.codeproject.com/ 国外著名的社区网站,面向世界的程序员.有很多不错的程序都可以从那里下载到. 4.htt

双目测距的基本原理(转http://blog.csdn.net/chenyusiyuan/article/details/5961769)

双目测距的基本原理 如上图所示,双目测距主要是利用了目标点在左右两幅视图上成像的横向坐标直接存在的差异(即视差)与目标点到成像平面的距离Z存在着反比例的关系:Z=fT/d.“@scyscyao :在OpenCV中,f的量纲是像素点,T的量纲由定标板棋盘格的实际尺寸和用户输入值确定,一般是以毫米为单位(当然为了精度提高也可以设置为0.1毫米量级),d=xl-xr的量纲也是像素点.因此分子分母约去,Z的量纲与T相同. ” 假设目标点在左视图中的坐标为(x,y),在左右视图上形成的视差为d,目标点在以

稀疏编码(Sparse Coding)的前世今生(一) 转自http://blog.csdn.net/marvin521/article/details/8980853

稀疏编码来源于神经科学,计算机科学和机器学习领域一般一开始就从稀疏编码算法讲起,上来就是找基向量(超完备基),但是我觉得其源头也比较有意思,知道根基的情况下,拓展其应用也比较有底气.哲学.神经科学.计算机科学.机器学习科学等领域的砖家.学生都想搞明白人类大脑皮层是如何处理外界信号的,大脑对外界的“印象”到底是什么东东.围绕这个问题,哲学家在那想.神经科学家在那用设备观察.计算机和机器学习科学家则是从数据理论和实验仿真上推倒.仿真.在神经编码和神经计算领域,我所能查到最早关于稀疏编码的文献是199