KMP(模板)
kmp算法是解决单模匹配问题的算法,难点在于求next[]数组
求next[]数组:对于子串的所有前缀子串的最长公共前后缀的长度,就是next[]数组的值
首先,要了解两个概念:"前缀"和"后缀"。 "前缀"指除了最后一个字符以外,一个字符串的全部头部组合;"后缀"指除了第一个字符以外,一个字符串的全部尾部组合。如下图所示:
下面再以”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。
eg:主串为cbbbaababac 子串为ababac
初始化next[0]=-1;
子串的最长公共前后缀长度
a -->0 next[1]=0 a的前缀为空,后缀也为空,共有元素的长度为0
ab -->0 next[2]=0 ab前缀为[a],后缀为[b],共有元素的长度为0
aba -->1 next[3]=1 前缀为[a,ab],后缀为[a,ba],共有元素的长度为1
abab -->2 next[4]=2 前缀为[a,ab,aba],后缀为[b,ab,bab],共有元素的长度为2
ababa -->3 next[5]=3 前缀为[a,ab,aba,abab],后缀也为[a,ba,aba,baba],共有元素的长度为3
next[i]数组的作用是在当子串字母s[i]在和主串字母p[j]失配的时候,next[i]数组提供一个值,子串整体移动( i-next[i] )个位置,继续用s[next[i]]去和主字母p[j]匹配
eg:模板串是cbbbaababac,子串是ababa
子串下标: 0 1 2 3 4
a b a b a
失配跳转位置next[]: -1 0 0 1 2
这里解释一下:当子串和主串失配的时候,就根据next[]的值移动子串到相应位置去和主串匹配。当子串next[]值为-1的时候,主串的当前匹配位置后移一个字母
这里模拟一下匹配过程,i表示主串的当前匹配位置,j表示子串的当前匹配位置,初始i=0,j=0;主串p[],子串s[]
a!=c ---> i++ i=1,j=0
a!=b ---> i++ i=2,j=0
a!=b ---> i++ i=3,j=0
a!=b ---> i++ i=4,j=0
a==a ---> i++,j++ i=5,j=1
b!=a ---> i保持不变,j=next[j],跳转 i=5,j=0
a==a ---> i++,j++ i=6,j=1
b==b ---> i++,j++ i=7,j=2
a==a ---> i++,j++ i=8,j=3
b==b ---> i++,j++ i=9,j=4
a==a ---> i++,j++ i=10,j=5
j>=strlen(s) 匹配结束 , 返回可以匹配的首地址 return j-i+1
#include<iostream>
#include<string.h>
using namespace std;
char p[],s[];
int next1[];
void get_next(char *s,int *next1)
{
int m=strlen(s);//子串的长度
int j=;//当前匹配的位置
int k=-;//失配的时候要跳转的位置(也是最长公共前后缀的长度)
next1[]=-;
while(j<m)
{
if(k==-||s[j]==s[k])
next1[++j]=++k;
else
k=next1[k];
}
}
int kmp(char *p,char *s)//p是模板串,s是子串
{
int i=,j=;
int n=strlen(p);
int m=strlen(s);
while(i<n&&j<m)
{
if(j==-||p[i]==s[j])
{
i++;
j++;
}
else
j=next1[j];
}
if(j>=m)//s串比较完毕
return i-m+;
else
return -;
} int main()
{
cin>>p>>s;
get_next(p,next1);
for(int i=;s[i];i++)
cout<<"next["<<i<<"]="<<next1[i]<<endl;
cout<<"从第"<<kmp(p,s)<<"个字符开始匹配"<<endl;//返回的是开始匹配的第几个字符,不是位置
return ;
}
KMP(模板)的更多相关文章
- hdu 1686 KMP模板
// hdu 1686 KMP模板 // 没啥好说的,KMP裸题,这里是MP模板 #include <cstdio> #include <iostream> #include ...
- Oulipo HDU 1686 KMP模板
题目大意:求模式串在主串中的出现次数. 题目思路:KMP模板题 #include<iostream> #include<algorithm> #include<cstri ...
- KMP模板(bin)
KMP模板 主要是kuangbin的模板,之后加了一点我的习惯和理解. kmpN() 作用:构造next数组 参数:模式串,模式串长度 kmpC() 作用:返回模式串在主串中出现的次数(可重复) 参数 ...
- HDU 1711 - Number Sequence - [KMP模板题]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1711 Time Limit: 10000/5000 MS (Java/Others) Memory L ...
- HDU 1711 Number Sequence(KMP模板)
http://acm.hdu.edu.cn/showproblem.php?pid=1711 这道题就是一个KMP模板. #include<iostream> #include<cs ...
- 剪花布条---hdu2087(kmp模板)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2087 kmp模板题: #include <cstdio> #include <cst ...
- Oulipo----poj3461(kmp模板)
题目链接:http://poj.org/problem?id=3461 和 减花布条 的题对比一下: 求s2中s1的个数kmp模板: #include<stdio.h> #include& ...
- kmp模板 && 扩展kmp模板
kmp模板: #include <bits/stdc++.h> #define PB push_back #define MP make_pair using namespace std; ...
- kuangbin专题16B(kmp模板)
题目链接: https://vjudge.net/contest/70325#problem/B 题意: 输出模式串在主串中出现的次数 思路: kmp模板 在 kmp 函数中匹配成功计数加一, 再令 ...
- [HDU1711]KMP模板
解题关键:1.直接套kmp模板即可,注意最后输出的位置,需要在索引的位置+1. 2.next用作数组名在oj中会编译错误, 3.选用g++,只有g++才会接受bits/stdc++.h OJ中g++和 ...
随机推荐
- ECMAScript中的箭头函数 (=>) 使用注意事项
箭头函数表达式的语法比函数表达式更简洁,并且没有自己的this,arguments,super或 new.target.这些函数表达式更适用于那些本来需要匿名函数的地方,并且它们不能用作构造函数. 箭 ...
- EF 查询表达式 join
数据源: 1.无into,相当于 inner join var query = from p in context.P join s in context.S on p.PID equals s.PI ...
- 如何在应用程序中使用ML.NET?
https://www.cnblogs.com/shanyou/p/9190701.html ML.NET以NuGet包的形式提供,可以轻松安装到新的或现有的.NET应用程序中. 该框架采用了用于其他 ...
- 一个简单的C++程序及说明
一个简单的C++程序: #include<iostream> //头文件,因为输入cin,输出cout需要iostream using namespace std; //C++标准程序库中 ...
- ROS学习资源
1.ROS机器人操作系统自主学习实践环境 https://www.shiyanlou.com/courses/854 2.ROS官方网站 http://wiki.ros.org/ ROS中文官方网站 ...
- 基于scikitlearn的深度学习环境安装(三)(完整版)
OS Linux Ubuntu14.04 安装 pip (python2.7.9或以上自带pip) sudo apt-get install python-pip pip是python环境下安装包的 ...
- Python学习第二十六课——PyMySql(python 链接数据库)
Python 链接数据库: 需要先安装pymysql 包 可以设置中安装,也可以pip install pymysql 安装 加载驱动: import pymysql # 需要先安装pymysql 包 ...
- Python语言——map/reduce的用法
Python内建了map()和reduce()函数. 如果你读过Google的那篇大名鼎鼎的论文“MapReduce: Simplified Data Processing on Large Clus ...
- Python基础语法笔记2
------------------------------------------------------------------------------- 常量和Pylint的规范 1.常量:常量 ...
- TomcatJVM参数优化降低内存使用率(重点)!
JVM是jdk最底层的支柱 做JVM参数优化主要是为了改善服务器性能以及内存使用率 JAVA堆分为三大部分:(新生代.老年代.永久代) ================================ ...