字符串匹配算法 之BF、KMP
示例:
1. 已知字符串str1="acabaabaabcacaabc",求str2="abaabcac"是否在字符串str1中?
2. DNA病毒检测。已知患者DNA序列求病毒DNA序列是否在患者DNA中出现过?病毒DNA为环状结构(即首尾相连)。
此文以问题1为例进行解答。
一、BF算法:
即暴力检测法,从字符串第一个字符开始和匹配字符串进行比较如果不同,则从字符串第二个位置开始比较直到结束。
BF算法思想很简单,直接列出代码实现:
static void Main(string[] args)
{
string str = "acabaabaabcacaabc";//"aaabaaaaaab";
string mo = "abaabc";//"aaaab";int flag;//表示查询结果
flag = BF(str, mo, );
if (flag != -) Console.WriteLine("匹配成功!" + " 下标为: " + flag);
else Console.WriteLine("匹配失败!");
}
private static int BF(string str, string mo, int v)
{
int i = v ,j = ;
while (i < str.Length && j < mo.Length)
{
if (str[i] == mo[j])
{
i++;
j++;
}
else
{
i = i - j + ;
j = ;
}
}
if (j >= mo.Length) return i - mo.Length;
else return -;
}
二、KMP算法:
如图:

在检测中发现i和j标记的元素不同,此时如果是BF算法直接ii= i-j+1,j = 0.但是KMP算法思想是让i下标不变,j下标变化,即可以理解为数组str2右移尽可能少的单位。
问题来了,如何知道要移动多少呢?

如图,我们可以知道,在数组str2中j下标之前的所有元素都和数组str1的对应位匹配,那么我们只要保证,将str2数组向右移动k,使得在str2中j=k元素之前的元素依旧匹配即可。因此引入
前缀和后缀的概念,前缀:元素的真子集 ,后缀:元素的反向真子集。即如aba三个元素,最长前缀为ab,最长后缀为ba。但是只有前缀a和后缀a相同所以str2的第四个元素的
next值为1;也就是当匹配到str[3]不同于str1时,此时j下标变为1即str2向右移动到j==下标1。
为此我们只需要根据str2得到next数组就行。即得到str2的最大匹配前后缀个数。默认a[0]=0;即变化值为next值-1.因为next值是在字符串下标从1开始,我们开发通常下标从0开始

代码如下:
static void Main(string[] args)
{
string str = "acabaabaabcacaabc";//"aaabaaaaaab";
string mo = "abaabc";//"aaaab";
int[] next=new int[mo.Length];
int flag;//表示查询结果
setNext(mo, next);
foreach (var item in next)
{
Console.Write(item + " ");
}
Console.WriteLine();
flag = KMP(str, mo, , next);
if (flag != -) Console.WriteLine("匹配成功!" + " 下标为: " + flag);
else Console.WriteLine("匹配失败!");
}
private static void setNext(string mo, int[] next)
{
int i = , j = -;
next[] = -;
while (i < mo.Length - )
{
if (j == - || mo[i] == mo[j])
{
i++; j++;
next[i] = j;
}
else j = next[j];
}
}
private static int KMP(string str, string mo, int v,int[] next)
{
int i = v, j = ;
while (i < str.Length && j < mo.Length)
{
if (j==- || str[i] == mo[j])
{
i++;
j++;
}
else
{
j = next[j];
}
}
if (j >= mo.Length) return i - mo.Length;
else return -;
}
//进一步对next数组优化
private static void setNextVal(string mo, int[] next)
{
int i = , j = -;
next[] = -;
while (i < mo.Length-)
{
if (j == - || mo[i] == mo[j])
{
i++; j++;
if (mo[i] != mo[j]) next[i] = j;
else next[i] = next[j];
}
else j = next[j];
}
}
字符串匹配算法 之BF、KMP的更多相关文章
- 字符串匹配算法之BF(Brute-Force)算法
BF(Brute-Force)算法 蛮力搜索,比较简单的一种字符串匹配算法,在处理简单的数据时候就可以用这种算法,完全匹配,就是速度慢啊. 基本思想 从目标串s 的第一个字符起和模式串t的第一个字符进 ...
- 常用算法3 - 字符串查找/模式匹配算法(BF & KMP算法)
相信我们都有在linux下查找文本内容的经历,比如当我们使用vim查找文本文件中的某个字或者某段话时,Linux很快做出反应并给出相应结果,特别方便快捷! 那么,我们有木有想过linux是如何在浩如烟 ...
- 数据结构4_java---顺序串,字符串匹配算法(BF算法,KMP算法)
1.顺序串 实现的操作有: 构造串 判断空串 返回串的长度 返回位序号为i的字符 将串的长度扩充为newCapacity 返回从begin到end-1的子串 在第i个字符之前插入字串str 删除子串 ...
- Python 细聊从暴力(BF)字符串匹配算法到 KMP 算法之间的精妙变化
1. 字符串匹配算法 所谓字符串匹配算法,简单地说就是在一个目标字符串中查找是否存在另一个模式字符串.如在字符串 "ABCDEFG" 中查找是否存在 "EF" ...
- 数据结构学习之字符串匹配算法(BF||KMP)
数据结构学习之字符串匹配算法(BF||KMP) 0x1 实验目的 通过实验深入了解字符串常用的匹配算法(BF暴力匹配.KMP.优化KMP算法)思想. 0x2 实验要求 编写出BF暴力匹配.KM ...
- 数据结构- 串的模式匹配算法:BF和 KMP算法
数据结构- 串的模式匹配算法:BF和 KMP算法 Brute-Force算法的思想 1.BF(Brute-Force)算法 Brute-Force算法的基本思想是: 1) 从目标串s 的第一个字 ...
- 字符串匹配算法 - KMP
前几日在微博上看到一则微博是说面试的时候让面试者写一个很简单的字符串匹配都写不出来,于是我就自己去试了一把.结果写出来的是一个最简单粗暴的算法.这里重新学习了一下几个经典的字符串匹配算法,写篇文章以巩 ...
- KMP单模快速字符串匹配算法
KMP算法是由Knuth,Morris,Pratt共同提出的算法,专门用来解决模式串的匹配,无论目标序列和模式串是什么样子的,都可以在线性时间内完成,而且也不会发生退化,是一个非常优秀的算法,时间复杂 ...
- 【原创】通俗易懂的讲解KMP算法(字符串匹配算法)及代码实现
一.本文简介 本文的目的是简单明了的讲解KMP算法的思想及实现过程. 网上的文章的确有些杂乱,有的过浅,有的太深,希望本文对初学者是非常友好的. 其实KMP算法有一些改良版,这些是在理解KMP核心思想 ...
随机推荐
- iOS 部分API理解
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typica ...
- 量化投资_TB交易开拓者A函数和Q函数常见组合应用
1 在交易开拓者当中,关于交易的做单方式一般分为:图表函数和A函数两类. 两类的主要区别为:如果采用图表函数的话,所有的交易内容都是以图表上面的信号为准,当前仓位运行的实际状态是没有的,但是可以显示交 ...
- 4412开发板QtE系统下MT6620-wifi的测试
基于iTOP4412系统烧写并启动之后,使用如下命令.wpa_passphrase XXX "YYY " >> /etc/wpa_supplicant.conf其中 X ...
- Eclipse中配置使用本地schema或dtd文件
问题:在设备不能正常联网的情况下,无法获取到网络上的 dtd 或 schema,编写配置文件的 XML 文档就没有了提示功能. 一般情况下,下载的 Jar 包或者 Zip 包中都会包含需要的 sche ...
- P2486 [SDOI2011]染色 区间合并+树链剖分(加深对线段树的理解)
#include<bits/stdc++.h> using namespace std; ; struct node{ int l,r,cnt,lazy; node(,,,):l(l1), ...
- docker里修改时间
在docker容器里,你会发现,你根本无法通过命令修改时间.这时我们就可以通过/etc/localtime这个配置文件修改时间了.但这个配置文件是一个二进制的文件,里面根本就是一堆乱码.所以我只好拷贝 ...
- java 的CAS
CAS:什么是 CAS 机制?cas目的是实现原子操作解释一下:"原子操作(atomic operation)是不需要synchronized",这是多线程编程的老生常谈了.所谓原 ...
- wareshark判断一个http请求链接是否断开
使用curl -v www.baidu.com发送一个请求 使用wareshark的过滤器表达式显示这个完整请求 TCP HTTP协议 , 其中192.168.1.4是本地ip 可以看到84 85两个 ...
- 2)PHP代码运行过程
https://zhidao.baidu.com/question/544575728.html
- PyCharm4.5 中文破解版破解步骤
1.在下载之家下载PyCharm4.5中文版软件包,然后右击软件安装包选择解压到“pycharm4.5.3”. 2.在解压文件夹中找到pycharm-professional-4.5.3,右击打开. ...