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. ssh禁止密码登录

    1.root用户登陆后,运行以下第一句指令,其他根据提示进行输入: ssh-keygen -t rsaGenerating public/private rsa key pair.Enter file ...

  2. vxworks下文件读写示例

    dev 1.create file on floopy disk and write contents: -> pdev=fdDevCreate(0,0,0,0)     /* A:,1.44M ...

  3. gstreamer在Ubuntu下构建开发环境

    1,Ubuntu已经安装了gstreamer库,因此只需要再安装几个开发库即可,是 libstreamer0.-libstreamer0.-devlibstreamer0.--dbg 在新立得里选中应 ...

  4. 小白学爬虫-设置Selenium+Chrome代理

    微博登录限制了错误次数···加上Cookie大批账号被封需要从Cookie池中 剔除被封的账号··· 需要使用代理··· 无赖百度了大半天都是特么的啥玩意儿???结果换成了 Google手到擒来 分分 ...

  5. 用.Net Core控制台模拟一个ASP.Net Core的管道模型

    在我的上几篇文章中降到了asp.net core的管道模型,为了更清楚地理解asp.net core的管道,再网上学习了.Net Core控制台应用程序对其的模拟,以加深映像,同时,供大家学习参考. ...

  6. input 和button的区别

    一,区别一 先来看一个问题 <input type="button" class="btn-upload bg-org-code" name=" ...

  7. 使用sourceTree向码云提交代码时 push 错误 (或认证失败)解决办法

     如果出现push不进去或者使用命令push认证失败时,很可能是你密码有误或者用户冲突,解决办法如下: 1.进入目录,找到文件后先备份一下 注意:appData可能隐藏了,若是隐藏,先让其显示  2. ...

  8. [BZOJ1096] [ZJOI2007] 仓库建设 (斜率优化)

    Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L公司一般把产品直接堆放在露天,以节省费用.突然有一天, ...

  9. Django使用Celery异步任务队列

    1  Celery简介 Celery是异步任务队列,可以独立于主进程运行,在主进程退出后,也不影响队列中的任务执行. 任务执行异常退出,重新启动后,会继续执行队列中的其他任务,同时可以缓存停止期间接收 ...

  10. PHP 反射类学习记录

    原文:http://www.upwqy.com/details/58.html 1 开发环境 windows TP5 参考文档 http://php.net/manual/zh/class.refle ...