KMP算法

一、传统字符串匹配算法

/*
* 从s中第sIndex位置开始匹配p
* 若匹配成功,返回s中模式串p的起始index
* 若匹配失败,返回-1
*/
int index(const std::string &s, const std::string &p, const int sIndex = )
{
int i = sIndex, j = ; if (s.length() < || p.length() < || sIndex < )
{
return -;
} while (i != s.length() && j != p.length())
{
if (s[i] == p[j])
{
++i;
++j;
}
else
{
i = i - j + ;
j = ;
}
}
return j == p.length() ? i - j: -;
}

另外一种简单匹配:

int Index_BF ( char S [ ], char T [ ], int pos )
{
  /* 若串 S 中从第pos(S 的下标0≤pos<StrLength(S))个字符
  起存在和串 T 相同的子串,则称匹配成功,返回第一个
  这样的子串在串 S 中的下标,否则返回 -1 */   int i = pos, j = ;
  while ( S[i+j] != '\0'&& T[j] != '\0')
  {
    if ( S[i+j] == T[j] )
      j++; // 继续比较后一字符
    else
    {
      i ++;
      j = ; // 重新开始新的一轮匹配
    }  
  }   if ( T[j] == '\0')
     return i; // 匹配成功 返回下标
  else
     return -; // 串S中(第pos个字符起)不存在和串T相同的子串 } // Index_BF

二、KMP算法

//http://www.cppblog.com/oosky/archive/2006/07/06/9486.html

定义

(1)next[0]= -1  意义:任何串的第一个字符的模式值规定为-1。

(2)next[j]= -1   意义:模式串T中下标为j的字符,如果与首字符相同,且j的前面的1—k个字符与开头的1—k个字符不等(或者相等但T[k]==T[j])(1≤k<j)。

   如:T=”abCabCad” 则 next[6]=-1,因T[3]=T[6]

(3)next[j]=k    意义:模式串T中下标为j的字符,如果j的前面k个字符与开头的k个字符相等,且T[j] != T[k] (1≤k<j)。

即T[0]T[1]T[2]。。。T[k-1]==T[j-k]T[j-k+1]T[j-k+2]…T[j-1]  且T[j] != T[k].(1≤k<j);

( 4 ) next[j]=0   意义:除(1)(2)(3)的其他情况。

举例

01)求T=“abcac”的模式函数的值。

next[0]= -1  根据(1)

next[1]=0   根据 (4)   因(3)有1<=k<j;不能说,j=1,T[j-1]==T[0]

next[2]=0   根据 (4)   因(3)有1<=k<j;(T[0]=a)!=(T[1]=b)

next[3]= -1  根据 (2)

next[4]=1   根据 (3)  T[0]=T[3] 且 T[1]=T[4]

下标

0

1

2

3

4

T

a

b

c

a

c

next

-1

0

0

-1

1

若T=“abcab”将是这样:

下标

0

1

2

3

4

T

a

b

c

a

b

next

-1

0

0

-1

0

为什么T[0]==T[3],还会有next[4]=0呢, 因为T[1]==T[4], 根据 (3)” 且T[j] != T[k]”被划入(4)。

02)来个复杂点的,求T=”ababcaabc” 的模式函数的值。

  next[0]= -1    根据(1)

next[1]=0    根据(4)

next[2]=-1   根据 (2)

  next[3]=0   根据 (3) 虽T[0]=T[2] 但T[1]=T[3] 被划入(4)

  next[4]=2   根据 (3) T[0]T[1]=T[2]T[3] 且T[2] !=T[4]

  next[5]=-1  根据 (2)

  next[6]=1   根据 (3) T[0]=T[5] 且T[1]!=T[6]

  next[7]=0   根据 (3) 虽T[0]=T[6] 但T[1]=T[7] 被划入(4)

  next[8]=2   根据 (3) T[0]T[1]=T[6]T[7] 且T[2] !=T[8]

下标

0

1

2

3

4

5

6

7

8

T

a

b

a

b

c

a

a

b

c

next

-1

0

-1

0

2

-1

1

0

2

只要理解了next[3]=0,而不是=1,next[6]=1,而不是= -1,next[8]=2,而不是= 0,其他的好象都容易理解。

03)   来个特殊的,求 T=”abCabCad” 的模式函数的值。

下标

0

1

2

3

4

5

6

7

T

a

b

C

a

b

C

a

d

next

-1

0

0

-1

0

0

-1

4

next[5]= 0  根据 (3) 虽T[0]T[1]=T[3]T[4],但T[2]==T[5]

next[6]= -1  根据 (2) 虽前面有abC=abC,但T[3]==T[6]

next[7]=4   根据 (3) 前面有abCa=abCa,且 T[4]!=T[7]

若T[4]==T[7],即T=” adCadCad”,那么将是这样:next[7]=0, 而不是= 4,因为T[4]==T[7].

下标

0

1

2

3

4

5

6

7

T

a

d

C

a

d

C

a

d

next

-1

0

0

-1

0

0

-1

0

代码

#include <iostream.h>
#include <string.h>
using namespace std; void getNext(char *p,int *next)
{
int j,k;
next[]=-;
j=;
k=-;
while(j<strlen(p)-)
{
if(k==-||p[j]==p[k]) //匹配的情况下,p[j]==p[k]
{
j++;
k++;
next[j]=k;
}
else //p[j]!=p[k]
k=next[k];
}
} int KMPMatch(char *s,char *p)
{
int next[];
int i,j;
i=;
j=;
getNext(p,next);
while(i<strlen(s))
{
if(j==-||s[i]==p[j])
{
i++;
j++;
}
else
{
j=next[j]; //消除了指针i的回溯
}
if(j==strlen(p))
return i-strlen(p);
}
return -;
} int main()//abCabCad
{
char* text="bababCabCadcaabcaababcbaaaabaaacababcaabc";
char* pattern="abCab"; cout<< KMPMatch(text, pattern) << endl; return ;
}

Algorithm --> KMP算法的更多相关文章

  1. 【★】KMP算法完整教程

    KMP算法完整教程 全称:                               Knuth_Morris_Pratt Algorithm(KMP算法) 类型:                 ...

  2. 【★】KMP算法完整教程

    KMP算法完整教程 全称:                               Knuth_Morris_Pratt Algorithm(KMP算法) 类型:                 ...

  3. KMP算法完整教程 (上)

    KMP算法完整教程 全称: Knuth_Morris_Pratt Algorithm(KMP算法) 类型: 高级检索算法 功能: 字符串匹配查找 提出者: D.E.Knuth(克努兹),J.H.Mor ...

  4. !KMP算法完整教程

      KMP算法完整教程 全称:                               Knuth_Morris_Pratt Algorithm(KMP算法) 类型:                ...

  5. 从有限状态机的角度去理解Knuth-Morris-Pratt Algorithm(又叫KMP算法)

    转载请加上:http://www.cnblogs.com/courtier/p/4273193.html 在开始讲这个文章前的唠叨话: 1:首先,在阅读此篇文章之前,你至少要了解过,什么是有限状态机, ...

  6. 笔试算法题(52):简介 - KMP算法(D.E. Knuth, J.H. Morris, V.R. Pratt Algorithm)

    议题:KMP算法(D.E. Knuth, J.H. Morris, V.R. Pratt Algorithm) 分析: KMP算法用于在一个主串中找出特定的字符或者模式串.现在假设主串为长度n的数组T ...

  7. [Algorithm] 字符串匹配算法——KMP算法

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

  8. 萌新笔记——用KMP算法与Trie字典树实现屏蔽敏感词(UTF-8编码)

    前几天写好了字典,又刚好重温了KMP算法,恰逢遇到朋友吐槽最近被和谐的词越来越多了,于是突发奇想,想要自己实现一下敏感词屏蔽. 基本敏感词的屏蔽说起来很简单,只要把字符串中的敏感词替换成"* ...

  9. 【模式匹配】KMP算法的来龙去脉

    1. 引言 字符串匹配是极为常见的一种模式匹配.简单地说,就是判断主串\(T\)中是否出现该模式串\(P\),即\(P\)为\(T\)的子串.特别地,定义主串为\(T[0 \dots n-1]\),模 ...

随机推荐

  1. armlinux下的网路传输(tcp/ip)

    /*ex2serv.c*/ #include <time.h> #include<stddef.h> #include <stdio.h> #include < ...

  2. Visual Studio 2012 和 SVN 结合实现版本控制 AnkhSvn

    第一步: 安装VisualSVN Server Manager. 下载地址:http://www.onlinedown.net/soft/89603.htm 第二步: 安装TortoiseSVN.注意 ...

  3. IE浏览器兼容的常见问题及解决方案

    常见6个问题及解决方案 1 IE6/IE7对display:inline-block的支持还欠缺 就是我们做导航栏时通常会用到<ul><li>标签去写,在现在一些主流的浏览器中 ...

  4. jquery自带的方法

    5.1,$.trim $.trim("   Hello, chinaren_1123 & 摆渡浮桥!   "); //去掉前后空格后->Hello, chinaren ...

  5. C# 图解教程 第四章 类的基本概念

    类的基本概念 类的概述声明类 类成员字段方法 创建变量和类的实例为数据分配内存实例成员访问修饰符 私有访问和公用访问 从类的内部访问成员从类的外部访问成员综合应用 类的基本概念 类的概述 类是一种活动 ...

  6. 在linux下,怎么去查看一个运行中的程序, 到底是占用了多少内存

    1. 在linux下,查看一个运行中的程序, 占用了多少内存, 一般的命令有 (1). ps aux: 其中  VSZ(或VSS)列 表示,程序占用了多少虚拟内存. RSS列 表示, 程序占用了多少物 ...

  7. POJ 1791 Heavy Transportation(最大生成树)

    题面 Background Hugo Heavy is happy. After the breakdown of the Cargolifter project he can now expand ...

  8. emacs配置

    原配置 (global-set-key [f9] 'compile-file) (global-set-key [f10] 'gud-gdb) (global-set-key (kbd "C ...

  9. 【learning】[待完善]关于辛普森公式的一点想法

    [吐槽] 嗯一开始接触到这个东西其实是因为某道凸包的题目好像可以用这个奇妙的方法来算 但其实了解也不是很深,只是觉得这个东西十分有意思, 所以先稍微写一下自己的想法,了解更多之后慢慢完善 [正题] 首 ...

  10. JS合并两个数组的方法

    JS合并两个数组的方法 我们在项目过程中,有时候会遇到需要将两个数组合并成为一个的情况.比如: var a = [1,2,3]; var b = [4,5,6]; 有两个数组a.b,需求是将两个数组合 ...