模式匹配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中出现的位置. 输入格式: 输入有两行 ...
随机推荐
- jquery实现点击radio,当选中‘其它’时,显示后面输入框;否则隐藏
有时候会遇到这么一个很简单的功能: jquery实现点击radio,当选中‘其它’时,显示后面输入框:否则隐藏 html代码: <div> <input type="rad ...
- POJ 3304 Segments【叉积】
题意:有n条线段,问有没有一条直线使得所有线段在这条直线上的投影至少有一个共同点. 思路:逆向思维,很明显这个问题可以转化为是否有一条直线穿过所有线段,若有,问题要求的直线与该直线垂直,并且公共点为垂 ...
- AC日记——热浪 codevs 1557 (最短路模板题)
1557 热浪 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 德克萨斯纯朴的民眾们这个夏 ...
- 11SpringMvc_一个Action中,写多个类似的业务控制方法
我们要实现这么一个功能: 编写两个表单,提交到同一个Action中的不同的处理方法中.比如注册和登录,都提交到UserAction这个控制类中.但是这两个提交由userAction这个控制类不同的方法 ...
- [转]C# WinForm treeview checkbox----递归算法利用
在平常开发中,treeview的节点显示checkbox,若节点存在几级时,往往希望,选中父节点后,其子节点都要选中,如何实现勒,请看 using System; using System.Colle ...
- 获取元素的xpath, 转换xpath为csspath进行jQuery元素获取
获取元素的xpath, 转换xpath为csspath进行jQuery元素获取 博客分类: 编程心得 jQueryCSSHTML var $shadow = new Object(); /** 获取 ...
- C语言操作符优先级
C语言操作符优先级 优先级 运算符 含 义 要求运算 对象的个数 结合方向 1 () [] -> . 圆括号 下标运算符 指向结构体成员运算符 结构体成员运算符 自左至右 2 ! 逻辑非运 ...
- Android -- Scroller
Android里Scroller类是为了实现View平滑滚动的一个Helper类.通常在自定义的View时使用,在View中定义一个私有成员mScroller = new Scroller(conte ...
- Java系列:Add Microsoft SQL JDBC driver to Maven
Maven does not directly support some libraries, like Microsoft's SQL Server JDBC. This tutorial will ...
- linux实践——字符集
一.ASCII码 首先是看得懂ASCII码表: 二 八 十 十六 缩写/字符 0000 0000 0 0 00 NUL(null) 0000 0001 1 1 01 SOH(start of head ...