本文主要叙述用于字符串匹配的KMP算法。

  阮一峰的博文“字符串匹配的KMP算法"将该算法讲述得非常形象,可参考之。

字符串‘部分匹配值’计算

  KMP算法重要的一步在于部分匹配值的计算。模仿《算法导论》中的伪代码,对应的C++代码为:

 vector<int> partialMatching(string P)
{
int szP = P.size();
vector<int> pMatch;
pMatch.resize(szP);
// retVec[0] = 0;
int k = ;
for (int i = ; i < szP; i++)
{
while (k > && P[k] != P[i])
k = pMatch[k - ];
if (P[k] == P[i])
k = k + ;
pMatch[i] = k;
}
return pMatch;
}

  代码看起来挺简洁,但要理解起来就比较麻烦了。其中有一个问题就是:字符串“cabab”的部分匹配值为什么全都为0?其中的“ab”不是重复了吗,应该要算作重复的子串啊?

  之所以有这个困惑,是对字符串的前缀和后缀的概念不理解。在阮一峰的博文中,他提到"前缀"是指除了最后一个字符以外,一个字符串的全部头部组合;"后缀"指除了第一个字符以外,一个字符串的全部尾部组合。

  另外他还举了一个例子来说明如何求取一个字符串的部分匹配值:

    "部分匹配值"就是"前缀"和"后缀"的最长的共有元素的长度。以"ABCDABD"为例,
      - "A"的前缀和后缀都为空集,共有元素的长度为0;
      - "AB"的前缀为[A],后缀为[B],共有元素的长度为0;
      - "ABC"的前缀为[A, AB],后缀为[BC, C],共有元素的长度0;
      - "ABCD"的前缀为[A, AB, ABC],后缀为[BCD, CD, D],共有元素的长度为0;
      - "ABCDA"的前缀为[A, AB, ABC, ABCD],后缀为[BCDA, CDA, DA, A],共有元素为"A",长度为1;
      - "ABCDAB"的前缀为[A, AB, ABC, ABCD, ABCDA],后缀为[BCDAB, CDAB, DAB, AB, B],共有元素为"AB",长度为2;
      - "ABCDABD"的前缀为[A, AB, ABC, ABCD, ABCDA, ABCDAB],后缀为[BCDABD, CDABD, DABD, ABD, BD, D],共有元素的长度为0。

  注意:这个例子个人感觉如果没有好好理解,则有可能误解!阮一峰的做法是将一个字符串拆成不同长度的子串,然后求部分匹配值,而我们实际并不是这样子做的(参考上边代码),所以这些步骤可能会让我们误解后缀一定要以该字符串的最后一个字符来结束。

  对于一个字符串的前缀而言,一定要从第一个字符开始;而对其后缀而言,则不必要以最后一个字符结束。

KMP算法

  模仿《算法导论》中的伪代码,对应的C++代码为:

 vector<int> KMPMatching(string T, string P)
{
int szT = T.size();
int szP = P.size();
vector<int> pMatch = partialMatching(P);
vector<int> kmpMatch;
int k = ;
for (int i = ; i < szT; i++)
{
while (k > && T[i] != P[k])
k = pMatch[k - ]; if (T[i] == P[k])
k = k + ; if (k == szP - )
{
kmpMatch.push_back(i - k + );
k = pMatch[k - ];
}
}
return kmpMatch;
}

  注意,第19行的

k = pMatch[k - ];

  不能直接写成

k = ;

  例如待匹配字串为abababc,匹配模式为aba,则有两个符合匹配模式的子串:aba、aba,而中间的a是共享的。

"《算法导论》之‘字符串’":字符串匹配的更多相关文章

  1. 数据结构之 字符串---字符串匹配(kmp算法)

    串结构练习——字符串匹配 Time Limit: 1000MS Memory limit: 65536K 题目描述   给定两个字符串string1和string2,判断string2是否为strin ...

  2. 关于KMP算法理解(快速字符串匹配)

    参考:http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html 2016-08- ...

  3. 【算法与数据结构】字符串匹配之KMP算法

    // KMP.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> #include < ...

  4. 实现字符串匹配的KMP算法

    KMP算法是Knuth-Morris-Pratt算法的简称,它主要用于解决在一个长字符串S中匹配一个较短字符串s. 首先我们从整体来把我这个算法的思想. 字符串匹配的朴素算法: 我们容易想到朴素算法, ...

  5. 字符串匹配KMP算法的讲解C++

    转自http://blog.csdn.net/starstar1992/article/details/54913261 也可以参考http://blog.csdn.net/liu940204/art ...

  6. 字符串匹配之KMP

    说明 KMP算法看懂了觉得特别简单,思路很简单,看不懂之前,查各种资料,看的稀里糊涂,即使网上最简单的解释,依然看的稀里糊涂. 我花了半天时间,争取用最短的篇幅大致搞明白这玩意到底是啥. 这里不扯概念 ...

  7. 算法导论 (Thomas H.Cormen / Charles E.Leiserson / Ronald L.Rivest / Clifford Stein 著)

    第一部分 基础知识 第1章 算法在计算中的作用 第2章 算法基础 第3章 函数的增长 第4章 分治策略 第5章 概率分析和随机算法 第二部分 排序和顺序统计量 第6章 堆排序 第7章 快速排序 第8章 ...

  8. hrbustoj 1551:基础数据结构——字符串2 病毒II(字符串匹配,BM算法练习)

    基础数据结构——字符串2 病毒IITime Limit: 1000 MS Memory Limit: 10240 KTotal Submit: 284(138 users) Total Accepte ...

  9. 字符串匹配--kmp算法原理整理

    kmp算法原理:求出P0···Pi的最大相同前后缀长度k: 字符串匹配是计算机的基本任务之一.举例,字符串"BBC ABCDAB ABCDABCDABDE",里面是否包含另一个字符 ...

随机推荐

  1. linux源码编译安装OpenCV

    为了尽可能保证OpenCV的特性,使用OpenCV源码编译安装在linux上.先从安装其依赖项开始,以ubuntu 14.04.X为例讲解在Linux上源码编译安装OpenCV,其他linux版本可以 ...

  2. Android4.3 屏蔽HOME按键返回桌面详解(源码环境下)

    点击打开链接 首先声明我是做系统开发的(高通平台),所以下面介绍的方法并不适合应用开发者. 最经有个需求要屏蔽HOME按键返回桌面并且实现自己的功能,发现以前的方式报错用不了,上网搜索了一下,发现都是 ...

  3. 集合框架之Set接口

    一个不包含重复元素的 collection.更确切地讲,set 不包含满足e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个 null 元素. 在所有构造方法以及 add.equa ...

  4. Dynamics CRM Trace Reader for Microsoft Dynamics CRM

    CRM中抓取日志的视窗工作叫做Diagnastics Tools For Dyanmics CRM,这个工具我们只是作为一个开关来用就不做多介绍了,日志生成后是个文本文档可读性是很差的,那就需要个视窗 ...

  5. Android性能优化之Listview(ViewHolder重用机制)

    相信大家在很多时候都会用到ListView这个控件,因为确实是用的很多很多,但是有木有遇到过当数据很多很多的时候,往下滑ListView时有时候会卡顿,这就需要我们来优化它了. ListView优化主 ...

  6. 自定义圆角透明的Dialog

    自定义圆角透明的Dialog 说明 系统默认的Dialog默认是背景不透明的,有时候项目需要Dialog为圆角透明,这个时候的解决方案就是---重写Dialog - 系统样式 - 自定义以后的样式 自 ...

  7. Unable to access the IIS metabase.You do not have sufficient privilege

    今天在用vs打开以前老代码的时候报如下问题,无法打开工程了,从提示来不大可能是因为vs的版本引起的,本身我用的是最新版的vs. 网上查了下解决方法如下:找到你电脑中的如下路径"C:\Wind ...

  8. 程序员必须搞清的概念-equals和=和hashcode的区别

    1. 首先equals()和hashcode的介绍 equals 方法在非空对象引用上实现相等关系: * 自反性:对于任何非空引用值 x,x.equals(x) 都应返回 true. * 对称性:对于 ...

  9. HashMap方法介绍

    1. Map的遍历方式 (1) for each map.entrySet() Map<String, String> map = new HashMap<String, Strin ...

  10. 基于xml 实现动态加载权限功能树列表---EFSFrame企业级开发架构

    在学习EFSFrame框架的过程中,感触最深的就是通过xml来实现前台与后台数据的交互,页面设计灵活,不用管后台如何写的,前台与后台的交互唯一的交互通道都是xml,在我们需要添加页面.添加规定的格式的 ...