关于KMP算法的原理网上有很详细的解释,我试着总结理解一下:

KMP算法是什么

  以这张图片为例子

  

  匹配到j=5时失效了,BF算法里我们会使i=1,j=0,再看s的第i位开始能不能匹配,而KMP算法接下来就去比较T[2](next[5]=2)和S[5]

next数组什么意思?

就是当t[i]不匹配时,就让i=next[i]再去比较,则t[next[i]]前面的部分和s[j]前面一定是相同的,因为t[next[i]]前面的部分和t[i]前面的部分是相同的,图中相同颜色代表字符串相同部分。也就是我们利用模式串的自身匹配的特点,来减少和目标串的比较。

  

next数组怎么算?

我们算好next[i],去算next[i+1]时分两种情况:

  • T[i]==T[k] (k=next[i]) 时,next[i+1]=k+1。

  • T[i]!=T[k] 时,先看图左,在匹配的部分里(灰色)有更小的一段(蓝色),是next[next[i]]前面的子串,根据next数组的含义,蓝色的和粉色的子串相同,因为两段灰色是相同的,那左蓝就和右粉相同,
  • 如果这时Ti=Tnext[k],那next[i+1]就是next[k]+1,否则继续找更小的一段,直到k=-1,那么next[i]=0。
    void get_next(const string &T,int *next){
    int i=,k=-;
    next[i]=k;
    while(T[i]){
    if(k==-||T[k]==T[i])
    {
    ++k;
    ++i;
    next[i]=k;
    }else{
    k=next[k];
    }
    }
    }

但是其实还可以再改进

  上面算next[i+1]时不考虑T[i+1]是什么,T[i]失配,用T[next[i]]去比较,可以保证T[next[i]]前面的都能匹配,但是如果T[next[i]]==T[i],跳到next[i]肯定还是失配,所以算next时要考虑一下T[next[i]]和T[i]是否相等。

算好next[i],去算next[i+1]时:

   如果 T[k]==T[i]且T[i+1]==T[k+1],由于T[i+1]失配了,T[k+1]肯定也会失配,那next[i+1]应该继续跳到next[k+1]。

改进后的next计算代码:

void get_next()
{
int i=,k=-;
next[i]=k;
while(T[i])
{
if(k==-||T[i]==T[k])
{
++k;
++i;
if(T[i] == T[k])
next[i] = next[k];
else
next[i] = k;
}
else
k=next[k];
}
}

另一种get_next的写法

void get_next()
{
int i,k=-;
next[]=k;
for(i=;T[i];i++){
while(k>= && T[k+]!=T[i]) k=next[k];
if (T[k+]==T[i]) k++;
next[i]=k;
}
}

完整程序代码:

#include<iostream>
#include<cstring>
const int N = ; int next[N];
char T[N],S[N]; void get_next()
{
int i=,k=-;
next[i]=k;
while(T[i]){
if(k==-||T[i]==T[k]){
++i;
++k;
if(T[i]==T[k])
next[i]=next[k];
else
next[i]=k;
}else{
k=next[k];
}
}
} int KMP()
{
int i=,j=;
while(S[j]&&(i==-||T[i])){
if(i==-||S[j]==T[i]){
++i;
++j;
}else{
i=next[i];
}
}
if(!T[i])return j-i;
return -;
} int main(){
std::cin>>T>>S;
get_next();
std::cout<<KMP()+<<std::endl;
return ;
}
/*
abcaccdacb
abcaccdaccccaccabcaccdaccacabcaccdacb
输出28
*/

  

模式匹配KMP算法的更多相关文章

  1. 字符串模式匹配KMP算法

    一篇不错的博客:http://www.cnblogs.com/dolphin0520/archive/2011/08/24/2151846.html KMP字符串模式匹配通俗点说就是一种在一个字符串中 ...

  2. 字符串模式匹配——KMP算法

    KMP算法匹配字符串 朴素匹配算法   字符串的模式匹配的方法刚开始是朴素匹配算法,也就是经常说的暴力匹配,说白了就是用子串去和父串一个一个匹配,从父串的第一个字符开始匹配,如果匹配到某一个失配了,就 ...

  3. 模式匹配-KMP算法

    /***字符串匹配算法***/ #include<cstring> #include<iostream> using namespace std; #define OK 1 # ...

  4. 数据结构4.3_字符串模式匹配——KMP算法详解

    next数组表示字符串前后缀匹配的最大长度.是KMP算法的精髓所在.可以起到决定模式字符串右移多少长度以达到跳跃式匹配的高效模式. 以下是对next数组的解释: 如何求next数组: 相关链接:按顺序 ...

  5. 字符串模式匹配之KMP算法图解与 next 数组原理和实现方案

    之前说到,朴素的匹配,每趟比较,都要回溯主串的指针,费事.则 KMP 就是对朴素匹配的一种改进.正好复习一下. KMP 算法其改进思想在于: 每当一趟匹配过程中出现字符比较不相等时,不需要回溯主串的 ...

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

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

  7. 串的模式匹配和KMP算法

    在对字符串的操作中,我们经常要用到子串的查找功能,我们称子串为模式串,模式串在主串中的查找过程我们成为模式匹配,KMP算法就是一个高效的模式匹配算法.KMP算法是蛮力算法的一种改进,下面我们先来介绍蛮 ...

  8. 利用KMP算法解决串的模式匹配问题(c++) -- 数据结构

    题目: 7-1 串的模式匹配 (30 分) 给定一个主串S(长度<=10^6)和一个模式T(长度<=10^5),要求在主串S中找出与模式T相匹配的子串,返回相匹配的子串中的第一个字符在主串 ...

  9. (原创)数据结构之利用KMP算法解决串的模式匹配问题

      给定一个主串S(长度<=10^6)和一个模式T(长度<=10^5),要求在主串S中找出与模式T相匹配的子串,返回相匹配的子串中的第一个字符在主串S中出现的位置. 输入格式: 输入有两行 ...

随机推荐

  1. win10自动更新彻底关闭

    http://app.techweb.com.cn/wp/2016-10-24/2418646.shtml

  2. this关键字的使用

    一,表示类中属性 1,没有使用this的情况 class Person{ // 定义Person类 private String name ; // 姓名 private int age ; // 年 ...

  3. RDLC使用手册_RDLC报表部署

    原文:http://blog.csdn.net/lwjnumber/article/details/6590545 9.  RDLC报表部署(限于rdlc报表 windows应用程序) 1)    R ...

  4. 替换空格-请实现一个函数,将一个字符串中的空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

    class Solution { public: void replaceSpace(char *str,int length) { char *tmp; ; int i; ;i<length; ...

  5. JAVA NIO是什么(zz)

    JAVA NIO是什么? 1.   基本 概念 IO 是主存和外部设备 ( 硬盘.终端和网络等 ) 拷贝数据的过程. IO 是操作系统的底层功能实现,底层通过 I/O 指令进行完成. 所有语言运行时系 ...

  6. Python解析器源码加密系列之(二):一次使用标准c的FILE*访问内存块的尝试

    摘要:由于近期打算修改Python解释器以实现pyc文件的加密/解密,出于保密的要求,解密之后的数据只能放在内存中,不能写入到文件中.但是后续的解析pyc文件的代码又只能接受FILE*作为入参,所以就 ...

  7. 信息安全系统设计基础exp_4

    北京电子科技学院(BESTI) 实     验    报     告 课程:信息安全系统设计基础 班级:1353 姓名:郑伟.吴子怡 学号:20135322.20135313 指导教师: 娄嘉鹏 实验 ...

  8. 20145219 gdb调试汇编堆栈分析

    20145219 gdb调试汇编堆栈分析 代码gdbdemo.c int g(int x) { return x+19; } int f(int x) { return g(x); } int mai ...

  9. (转)shell实例手册

    原文地址:http://hi.baidu.com/quanzhou722/item/f4a4f3c9eb37f02d46d5c0d9 实在是太好的资料了,不得不转 shell实例手册 0说明{ 手册制 ...

  10. Chrome扩展开发之一——Chrome扩展的文件结构

    目录: 0.Chrome扩展开发(Gmail附件管理助手)系列之〇——概述 1.Chrome扩展开发之一——Chrome扩展的文件结构 2.Chrome扩展开发之二——Chrome扩展中脚本的运行机制 ...