一、朴素模式

假设我们要从主串S=”goodgoogle"中找到子串T=“google"的位置,步骤如下:

i表示主串的当前位置下标,j表示子串的当前位置下标,如上图在第一轮比较(i=1开始)中j=4和i=4的位置不匹配,接下来就要指针回退,从i=2开始比较,如下:

如此反复直到比较到 i =(主串长度-子串长度+1)的位置或者 j = 子串的长度 就退出比较循环,上面的主串和子串在比较到i=5的位置就完全匹配了。

#include <stdio.h>

int Index(const char S[], const char T[], int pos){
int i = pos; //主串当前下标
int j = 1; //子串当前下标
//S[0]是主串的长度,T[0]是子串的长度
while(i <= S[0] && j <= T[0]){
//如果相等则继续向下比较
if(S[i] == T[j]) {
++i;
++j;
//如果不等则指针回退
}else{
i = i - j + 2; //主串回退
j = 1;
}
}
//j>T[0]则说明子串被完全匹配
if( j > T[0]) return i - T[0];
else return 0;
} int main(){
char S[] = {10, 'g', 'o', 'o', 'd', 'g', 'o', 'o',
'g', 'l', 'e'};
char T[] = {6, 'g', 'o', 'o', 'g', 'l', 'e'};
int i = Index(S, T, 1);
printf("%d\n", i); return 0;
}

分析一下这种匹配算法最好的情况时间复杂度是O(1)只需要一次比较,最坏的情况是每次最后一个字符不匹配,时间复杂度是O(m*n) m是主串长度n是子串的长度。

二、KMP算法

像二进制这样的多个0和1重复的字符串,上面的模式匹配需要挨个遍历是非常慢的,KMP算法可以大大避免重复遍历的情况。

下面我们来看看KMP算法的基本原理

如上,可以看到主串S和子串T在第一轮比较的时候,前面5个相等,只有i=6和j=6的位置不等。由于子串T中abcde这5个字符本身互不相等,可以知道子串T中a就不可能和j=2、3、4、5的位置的字符相等。所以可以直接跳到i=6的位置进行比较。

再看上图,如果子串T中存在重复的元素(比如j=1,2和j=4,5处的字符),按照上面的分析,我们可以直接跳到i=4的位置比较,但是我们已经知道j=1,2和j=4,5相等,并且i=4,5和j=4,5相等,所以可以不用比较i=4,5和j=1,2。

KMP模式匹配算法就是为了不让i指针回退,既然i值不回退,我们就要考虑变化j的值了。通过上面的观察可以发现,j值的变化与主串其实没有什么关系,而是取决于子串T中是否有重复问题。

我们把T串各个位置的j值的变化定义为一个数组next,那么next的长度就是T串的长度,可以得到下面函数:

#include <stdio.h>

void get_next(const char T[], int *next){

	int i,j;
i = 1;
j = 0;
next[1] = 0;
//T[0]是子串T的长度
while(i < T[0]){
//T[i]表示后缀的单个字符
//T[j]表示前缀的单个字符
if( j==0 || T[i] == T[j]){
++i;
++j;
next[i] = j;
}else{
j = next[j];
}
}
} int Index_KMP(const char S[], const char T[], int pos){
int i = pos;
int j = 1;
int next[255];
get_next(T, next); while(i <= S[0] && j <= T[0]){
//相对于朴素算法,增加了一个j==0的判断
if( j==0 || S[i] == T[j]){
++i;
++j;
}else{
//j回退到合适的位置,i的值不变
j = next[j];
}
}
if( j>T[0]){
return i-T[0];
}else{
return 0;
}
}
int main(){ return 0;
}

数据结构——串的朴素模式和KMP匹配算法的更多相关文章

  1. 字符串的朴素模式和KMP模式匹配

    先复习一下字符串指针: #include <iostream> #include <string.h> using namespace std; int main() { ch ...

  2. 数据结构- 串的模式匹配算法:BF和 KMP算法

      数据结构- 串的模式匹配算法:BF和 KMP算法  Brute-Force算法的思想 1.BF(Brute-Force)算法 Brute-Force算法的基本思想是: 1) 从目标串s 的第一个字 ...

  3. 4-4-串的KMP匹配算法-串-第4章-《数据结构》课本源码-严蔚敏吴伟民版

    课本源码部分 第4章  串 - KMP匹配算法 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接☛☛☛ <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码 ...

  4. 串的匹配:朴素匹配&amp;KMP算法

    引言 字符串的模式匹配是一种经常使用的操作. 模式匹配(pattern matching),简单讲就是在文本(text,或者说母串str)中寻找一给定的模式(pattern).通常文本都非常大.而模式 ...

  5. 搞定KMP匹配算法

    KMP算法介绍及实现——轻松搞定KMP匹配算法 本文介绍了字符串匹配算法中的BF算法和KMP算法.本文中KMP算法介绍部分是关于KMP算法相关文章中最简洁的一篇文章之一.下一篇将继续介绍Horspoo ...

  6. hdu3065 病毒侵袭持续中 AC自动机入门题 N(N <= 1000)个长度不大于50的模式串(保证所有的模式串都不相同), 一个长度不大于2000000的待匹配串,求模式串在待匹配串中的出现次数。

    /** 题目:hdu3065 病毒侵袭持续中 链接:http://acm.hdu.edu.cn/showproblem.php?pid=3065 题意:N(N <= 1000)个长度不大于50的 ...

  7. hdu2896 病毒侵袭 AC自动机入门题 N(N <= 500)个长度不大于200的模式串(保证所有的模式串都不相同), M(M <= 1000)个长度不大于10000的待匹配串,问待匹配串中有哪几个模式串,

    /** 题目:hdu2896 病毒侵袭 链接:http://acm.hdu.edu.cn/showproblem.php?pid=2896 题意:N(N <= 500)个长度不大于200的模式串 ...

  8. hdu2457(最少替换多少个字符使主串不包含模式串)ac自动机+dp

    题:http://acm.hdu.edu.cn/showproblem.php?pid=2457 题意:给定n个模式串,给定一个主串,问最替换掉多少个字符使主串不包含模式串或输出“-1”表示没有可行的 ...

  9. 痞子衡嵌入式:一种i.MXRT下从App中进入ROM串行下载模式的方法

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT下在App中利用ROM API进ISP/SDP模式的方法. 我们知道i.MXRT系列分为两大阵营:CM33内核的i.MXRT ...

随机推荐

  1. <Sicily>Polynomial

    一.题目描述 Given a polynomial and the value of the variable x, you task is to calculate the value of the ...

  2. C#中使用Dictionary实现Map数据结构——VC编程网

    转载自: http://blog.51cto.com/psnx168 在VC中使用过CMap以及在Java中使用过Map的朋友应该很熟悉,使用Map可以方便实现基于键值对数据的处理,在C#中,你就需要 ...

  3. POJ-1456 Supermarket 贪心问题 有时间限制的最小化惩罚问题

    题目链接:https://cn.vjudge.net/problem/POJ-1456 此题与HDU-1789完全是一道题 题意 有N件商品,分别给出商品的价值和销售的最后期限,只要在最后日期之前销售 ...

  4. 一次AIX LVM PV重复PVID故障处理记录

    故障背景:客户需要把AIX 5.3.10上的一些VG做两台存储之间的LVM级别的Mirror,存储使用的是两台EMC DMX3,但是由于两套SAN存储之前是使用EMC的软件做存储级别的Mirror,所 ...

  5. git error: object file .git/objects/b9/e269f50db2a3415cc8ad5ba40b82b9b6a13d45 is empty

    错误现象: 解决方法: 1.  find .git/objects/ -type f -empty | xargs rm 2. git fetch -p 3. git fsck --full

  6. HDU 4917 Permutation 拓扑排序的计数

    题意: 一个有n个数的排列,给你一些位置上数字的大小关系.求合法的排列有多少种. 思路: 数字的大小关系可以看做是一条有向边,这样以每个位置当点,就可以把整个排列当做一张有向图.而且题目保证有解,所以 ...

  7. 试图切换控制addChildViewController、_transitionFromViewController

    试图切换能够用transitionFromViewController. 步骤: View Controller中能够加入多个sub view,在须要的时候显示出来: 能够通过viewControll ...

  8. 受不了Android SDK文档打开缓慢问题,自己开发简易脱机浏览器。

    google android sdk离线文档打开的时候特别慢,据说是要从谷歌官网拉取一些东西导致的.脱机浏览能够解决该问题.PC端能够使用firefox. 可是Android端貌似没有支持脱机工作的浏 ...

  9. ubuntu12.04更新软件源时出现校验和不符

    在运行update命令之后.出现系统校验和不符.网上找了一些方法,最后在大神的帮助下最终攻克了! ! 1.更改 /etc/apt/apt.conf.d/00aptitude 文件,在最后一行增加: A ...

  10. mahout处理路透社语料步骤,转换成须要的格式

    首先下载路透社语料(百度就能够下载): 然后上传Linux 并解压到指定文件夹.Tips:此处我放在可 /usr/hadoop/mahout/reutersTest/reuters tar -zxvf ...