模式匹配KMP算法
关于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算法的更多相关文章
- 字符串模式匹配KMP算法
一篇不错的博客:http://www.cnblogs.com/dolphin0520/archive/2011/08/24/2151846.html KMP字符串模式匹配通俗点说就是一种在一个字符串中 ...
- 字符串模式匹配——KMP算法
KMP算法匹配字符串 朴素匹配算法 字符串的模式匹配的方法刚开始是朴素匹配算法,也就是经常说的暴力匹配,说白了就是用子串去和父串一个一个匹配,从父串的第一个字符开始匹配,如果匹配到某一个失配了,就 ...
- 模式匹配-KMP算法
/***字符串匹配算法***/ #include<cstring> #include<iostream> using namespace std; #define OK 1 # ...
- 数据结构4.3_字符串模式匹配——KMP算法详解
next数组表示字符串前后缀匹配的最大长度.是KMP算法的精髓所在.可以起到决定模式字符串右移多少长度以达到跳跃式匹配的高效模式. 以下是对next数组的解释: 如何求next数组: 相关链接:按顺序 ...
- 字符串模式匹配之KMP算法图解与 next 数组原理和实现方案
之前说到,朴素的匹配,每趟比较,都要回溯主串的指针,费事.则 KMP 就是对朴素匹配的一种改进.正好复习一下. KMP 算法其改进思想在于: 每当一趟匹配过程中出现字符比较不相等时,不需要回溯主串的 ...
- 【模式匹配】KMP算法的来龙去脉
1. 引言 字符串匹配是极为常见的一种模式匹配.简单地说,就是判断主串\(T\)中是否出现该模式串\(P\),即\(P\)为\(T\)的子串.特别地,定义主串为\(T[0 \dots n-1]\),模 ...
- 串的模式匹配和KMP算法
在对字符串的操作中,我们经常要用到子串的查找功能,我们称子串为模式串,模式串在主串中的查找过程我们成为模式匹配,KMP算法就是一个高效的模式匹配算法.KMP算法是蛮力算法的一种改进,下面我们先来介绍蛮 ...
- 利用KMP算法解决串的模式匹配问题(c++) -- 数据结构
题目: 7-1 串的模式匹配 (30 分) 给定一个主串S(长度<=10^6)和一个模式T(长度<=10^5),要求在主串S中找出与模式T相匹配的子串,返回相匹配的子串中的第一个字符在主串 ...
- (原创)数据结构之利用KMP算法解决串的模式匹配问题
给定一个主串S(长度<=10^6)和一个模式T(长度<=10^5),要求在主串S中找出与模式T相匹配的子串,返回相匹配的子串中的第一个字符在主串S中出现的位置. 输入格式: 输入有两行 ...
随机推荐
- Web前端研发工程师编程能力飞升之路
今天看到这篇文章.写的非常有意思,于是转载了.看看我们都处于什么的阶段. [背景] 如果你是刚进入web前端研发领域,想试试这潭水有多深,看这篇文章吧:如果你是做了两三年web产品前端研发,迷茫找不着 ...
- Oracle 排序中使用nulls first 或者nulls last 语法
-原理 Nulls first和nulls last是Oracle Order by支持的语法 如果Order by 中指定了表达式Nulls first则表示null值的记录将排在最前(不管是asc ...
- 多线程BackgroundWorker
链接:http://www.cnblogs.com/yiyisawa/archive/2008/11/24/1339826.html 周六闲来无事,学习了多线程BackgroundWorker,以此记 ...
- scala学习之第二天:可变容器与不可变容器的特性与应用
1.具体的不可变集合实体类 List(列表) 是一种有限的不可变序列式.提供了常数时间的访问列表头元素和列表尾的操作,并且提供了常数时间的构造新链表的操作,该操作将一个新的元素插入到列表的头部.其他许 ...
- heartbeat初探
1,概念及原理 http://www.mingxiao.info/tag/heartbeat/
- 待整理-coredump
Linux下如何产生coredump(gdb调试用) 任务发生异常,需要记录遗言信息,利用gdb调试,因此需要记录coredump文件.设置查看:在root用户下执行sysctl -a | grep ...
- Winform调用百度地图接口
using System; using System.IO; using System.Collections.Generic; using System.ComponentModel; using ...
- 妙味WEB前端开发全套视频教程+项目实战+移动端开发(99G)
一共99GB的视频教程,全部存于百度网盘中,13个栏目,每个栏目里还划分有独立的小栏目 最基本的web前端学习介绍,到项目实战,再到移动端的开发,真正彻底掌握前端开发的精髓: 视频教程在线预览:(百度 ...
- Java Platform Standard Edition 8 Documentation
下面这个图挺有用的,收藏一下. Oracle has two products that implement Java Platform Standard Edition (Java SE) 8: J ...
- Linux常用的基本命令
man命令:查看帮助信息 格式:man 需要查看的命令 date命令:显示时间 格式:# date ...