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++和 ...
随机推荐
- Java数字和字符的对照关系表
/* 数字和字符的对照关系表(编码表): ASCII码表:American Standard Code for Information Interchange,美国信息交换标准代码. Unicode码 ...
- 微信+QQ跳转
加到对应页面的</body> 上面,或者<head> </head>之间 <script type="text/javascript"&g ...
- Codeforces Round #576 (Div. 2) 题解
比赛链接:https://codeforc.es/contest/1199 A. City Day 题意:给出一个数列,和俩个整数\(x,y\),要求找到序号最靠前的数字\(d\),使得\(d\)满足 ...
- 【笔记4-商品模块】从0开始 独立完成企业级Java电商网站开发(服务端)
分类管理模块 数据表结构设计 分类表 CREATE TABLE.mmall_ category' ( 'id' int(11) NOT NULL AUTO_ INCREMENT COMMENT ' 类 ...
- 世界协调时间(UTC)与中国标准时间
整个地球分为二十四时区,每个时区都有自己的本地时间.在国际无线电通信场合,为了统一起见,使用一个统一的时间,称为通用协调时(UTC, Universal Time Coordinated).UTC与格 ...
- php之新的开始---php的相关及其环境搭建
写在前面:首先,感谢“奇矩”给的这次机会,不论结果如何,我都会尽我最大的努力! 在今晚之前,如果说,我与php的接触是停留在知道的阶段,那今晚过后,我想我算是认识了php.php作为一门编程语言,已经 ...
- Redis为什么要自己实现一个SDS
Redis是使用C语言开发的,在C语言中没有字符串这种数据类型,字符串大都是通过字符数组实现的,但是使用字符数组有以下不足: 1. 字符数组的长度都是固定,容易发生空指针2. 获取字符数组的长度的时候 ...
- Leetcode 12,452,455-贪心算法
Leetcode第12题,整数转罗马数字,难度中等 整个题目比较好理解,难度也不大,就算不过脑子,用一串if也基本上可以解决问题,比如 /** 执行用时:6ms,在所有 Java 提交中击败了52.6 ...
- [03] Recursive Function递归应用
递归应用 1.理解 百科:一种计算过程,如果其中每一步都要用到前一步或前几步的结果,称为递归的: 理解:函数调用自己的过程,这类函数处理的事情具有重复性,处理此类实行可用while或者for,但结构上 ...
- 100w并发产生唯一随机id
#coding=utf-8 import time import base64 import getopt import sys import threading import random impo ...