文章目录

  • 字符串匹配
    • 字符串匹配暴力
    • kmp算法
      • next[i]数组的实现
      • kmp算法实现
    • kmp模板

字符串匹配

在常见的字符串相关的算法问题中有一种较为常见的是匹配问题,分为单模匹配与多模匹配,
多是要求我们在时限内计算单个或多个模式串在很长的一串原文串中的出现情况
单模匹配最好想到的就是时间复杂度O(n*m)的暴风(bf)算法,而当n和m是1e5量级的时候bf算法容易超时,
故而Knuth , Morris 和 Pratt 三人研究出了一种更加优秀的时间复杂度O(n+m)的算法去三人名称首字母
命名为KMP算法,自此单模匹配问题得到解决.
更难的多模匹配问题是通过AC自动机解决的,AC自动机简单的说就是利用字典树存储所有模式串,并使用KMP思
路在字典树上构造失败跳转指针,在匹配时将原文串与字典树进行模式匹配

字符串匹配暴力

void bf(const char*a,const char*b){int i=0,j,ans=0;while(a[i]){j = 0;while(b[j]&&a[i+j]==b[j])j++;if(!b[j])printf("原串%d下标位置匹配成功\n", i);i++;}
}

kmp算法

概念:
KMP是一种时间复杂度O(n+m)的字符串单模匹配算法,核心是通过预处理模式串的所有前缀串的最长相同前后缀,构造next数组,在原串与模式串匹配失败时参考next数组做跳转避免原串指针的回退并减少模式串指针的回退长度。
作用:
KMP算法的作用是在一个已知字符串中查找子串的位置,也叫做串的模式匹配。比如主串s=“goodgoogle”,子串t=“google”。
感谢博主 : https://blog.csdn.net/weixin_46007276/article/details/104372119
预备知识:
字符串 abcdab
前缀的集合:{a,ab,abc,abcd,abcda}
后缀的集合:{b,ab,dab,cdab,bcdab}
那么最长相等前后缀不就是ab嘛.

next[i]数组作用:
1.next[i]的值表示下标为i的字符前的字符串最长相等前后缀的长度。
2.表示该处字符不匹配时应该回溯到的字符的下标
匹配方式以及next[i]数组的作用含义:
在红色位置失配了,j 要重新匹配,那和模式串中哪个字符重新匹配呢?应该是已匹配部分的最长相同前后缀中前缀后一个字符,比如模式串abac当c失配时aba已匹配成功,最长相同前后缀是a,最长相同前缀后一个字符是b,所以原串失配字符下一次应该和b比较,因为我们的已匹配成功部分若想成为新的匹配成功情况的一部分必然是某后缀作为了模式串的前缀。
比如已匹配部分的最长相同前后缀长度若为x,则原串失配字符下一次就该与模式串第x+1个字符比对,而字符串0开始存的,第x+1个字符刚好在数组下标x的位置

next[i]数组的实现

实现逻辑:
next数组实现逻辑:
0下标对应的next值设置为某负数,因为next数组含义为最长相同前后缀长度,长度不可能为负数,故而实际上这是一个特殊值,因为若是连模式串的第一个字符都与失配位置没匹配上,则需要一个特殊值提醒原串指针后移模式串重新开始匹配。
然后从左到右推算每个位置的next值,用一个j记录当前[0,i)部分的最长相同前后缀长度,比较最长相同前缀后一个字符s[j]与新字符s[i]是否相同,相同则前后缀得到增长,否则j=next[j]比较次长相同前缀后一个字符是否与s[i]相同,直到j退为负数特殊值。将next值赋为0。

next[]数组的优化
这种情况出现的原因是当你的next数组回退之后,回退的字符与当前失配的模式串字符一样,那么这次匹配依旧会发生适配现象,所以在每次填入新的Next数组时,将其回退的字符与当前字符匹配一下,当字符一样的时候,再次跳转至上一个Next,
优化的作用是重新赋值next数组,.使匹配的速度更快

kmp算法实现

void getnext(char* s){int i=0,j=-1;next[i]=j;while(s[i]){//该条件为判断数组是否为空,可以根据题意改变if(j==-1||s[i]==s[j]){next[++i]=++j;if(s[i]==s[next[i]]){//优化这种情况出现的原因是当你的next数组回退之后,回退的next[i]==next[next[i]];//字符与当前失配的模式串字符一样,那么这次匹配依旧会发生适配现}//象,所以在每次填入新的Next数组时,将其回退的字符与当前}//字符匹配一下,当字符一样的时候,再次跳转至上一个Nextelse j=next[j];}
}
void kmp(char* a,char *b){getnext(b);int i=0,j=0,ans=0;while(a[i]){if(j==-1||a[i]==b[j]){i++,j++;if(!b[j]){//判断j加一后如果b数组到头了printf("原串%d位置匹配成功\n",i-strlen(b));ans++;//匹配成功的次数j=next[j];//跳回到上一个最长相同前后缀}}else j=next[j];}
}

kmp模板

next[i]数组作用:
1.next[i]的值表示下标为i的字符前的字符串最长相等前后缀的长度。
2.表示该处字符不匹配时应该回溯到的字符的下标
KMP字符串
给定一个模式串 S,以及一个模板串P,所有字符串中只包含大小写英文字母以及阿拉伯数字。
模板串 P 在模式串 S 中多次作为子串出现。
求出模板串 P 在模式串 S 中所有出现的位置的起始下标。
输入格式
第一行输入整数 N,表示字符串 P 的长度。
第二行输入字符串 P。
第三行输入整数 MM,表示字符串 S 的长度。
第四行输入字符串 S。
输出格式
共一行,输出所有出现位置的起始下标(下标从 0 开始计数),整数之间用空格隔开。
数据范围
1≤N≤105
1≤M≤106
输入样例:

3
aba
5
ababa

输出样例:

0 2

AC代码
** 数组从1开始存储 ,然后ne数组匹配答案串,ne[1]=0,然后ne数组中的i表示前i位可以匹配的相同前后缀,j的坐标每次都比i小1 **

#include <iostream>using namespace std;
const int N = 100010, M = 1000010;int n, m;
int ne[N];
char s[M], p[N];int main(){cin >> n >> p + 1 >> m >> s + 1;//下标均从1开始for (int i = 2, j = 0; i <= n; i ++ ){ //j表示匹配成功的长度,i表示p数组中的下标,因为p数组的下标是从1开始的,只有1个时,一定为0,所以i从2开始while (j && p[i] != p[j + 1]) j = ne[j];//如果不行可以换到next数组if (p[i] == p[j + 1]) j ++ ;//成功了就加1ne[i] = j;//得到ne数组的值//对应其下标}for (int i = 1, j = 0; i <= m; i ++ ){while (j && s[i] != p[j + 1]) j = ne[j];if (s[i] == p[j + 1]) j ++ ;if (j == n){printf("%d ", i - n);//第一次匹配成功的位置 j = ne[j];//然后回跳,接着找 }}return 0;
}

字符串匹配 (KMP)相关推荐

  1. 字符串匹配KMP算法

    字符串匹配KMP KMP过程其实就是去找下一个更好的状态的过程,省略去了中间穷举的无用过程,直接跳到下一个更好的状态,通过模式串本身的信息,站在模式串的角度来考虑问题 取长的一对 若想让模式串直接从S ...

  2. kmp算法详解php,php中字符串匹配KMP算法实现例子

    KMP算法是一个比较高级的算法了,加了改进了,下面我们来在php中实现KMP算法,希望例子对各位同学会带来帮助哦. kmp算法是一种改进的字符串匹配算法,由D.E.Knuth与V.R.Pratt和J. ...

  3. C++实现字符串匹配KMP算法

    文章目录 1. 概述 2. 代码实现 3. 代码测试 1. 概述 Kmp算法的介绍及思想参阅下面两篇文章: 字符串匹配KMP算法 算法)通俗易懂的字符串匹配KMP算法及求next值算法 2. 代码实现 ...

  4. 字符串匹配 KMP算法

    问题描述:字符串匹配即查找待匹配字符串(模式串)p在主串s中的位置.一般处理这种问题往往采用简单粗暴的方法--暴力匹配法.所谓暴力匹配法,就是对主串s的每一个字符与要匹配的字符串p的每个字符进行逐一匹 ...

  5. 字符串匹配——KMP算法

    字符串匹配--KMP算法 ​ 字符串匹配是计算机编程中最常使用到的基础算法之一.字符串匹配相关的算法很多,Knuth-Morris-Pratt(KMP)算法是最常用的之一.最近在学习KMP算法,学习了 ...

  6. 字符串匹配のKMP【专题@AbandonZHANG】

    算法详解 很长时间内都没有能够很理解KMP算法的精髓,尤其是很多书上包括<算法导论>没有把next函数(亦或 π函数)讲解的很透彻. 今天去看了matrix67大牛博客中关于kmp部分的讲 ...

  7. C语言实现字符串匹配KMP算法

    相信很多人(包括自己)初识KMP算法的时候始终是丈二和尚摸不着头脑,要么完全不知所云,要么看不懂书上的解释,要么自己觉得好像心里了解KMP算法的意思,却说不出个究竟,所谓知其然不知其所以然是也. 字符 ...

  8. [JAVA][算法] [字符串匹配]KMP

    我们为什么需要KMP? 在字符串匹配问题中,我们需要找到匹配串pattern在原串text中的位置,一种显而易见的思路就是暴力匹配,如图所示,我们把pattern放置到text中的每个位置进行比较即可 ...

  9. 字符串匹配KMP算法的讲解C++

    转自http://blog.csdn.net/starstar1992/article/details/54913261 也可以参考http://blog.csdn.net/liu940204/art ...

  10. 字符串匹配のKMP【@Abandon】

    算法详解 很长时间内都没有能够很理解KMP算法的精髓,尤其是很多书上包括<算法导论>没有把next函数(亦或 π函数)讲解的很透彻. 今天去看了matrix67大牛博客中关于kmp部分的讲 ...

最新文章

  1. ADB Server 错误的解决办法
  2. 《Selenium自动化测试指南》—第1章1.1节自动化测试基础
  3. uefi装完系统后无法引导_系统安装完后再设置uefi启动 - 卡饭网
  4. DDOS***类型以及iptables防范ddos脚本
  5. 高仿真的类-请求参数映射
  6. mysql 查询执行过程_深入浅出Mysql(一)——sql查询执行过程
  7. finally块不被执行的情况总结
  8. python美化输出模块_python日志处理模块
  9. cef3实现点击按钮弹出页面_Cef功能开发经验总结
  10. docker日志引擎说明
  11. FMEA失效模式和影响分析中措施优先级AP值的方法
  12. 射频微电子学_专注于射频前端芯片,苏州汉天下完成新一轮融资
  13. 小众绿软|媒体:myPlayer 2.1
  14. 计算机系统的四种启动方式是,电脑启动方式有几种你知道吗?
  15. Detecting Novel Associations in Large Data Sets(检测 大型数据集中的信息关联性,数据相关性)
  16. Kubernetes单机开发环境部署记录
  17. P4086 [USACO17DEC]My Cow Ate My Homework S(静态数据预处理:后缀和、后缀最小值)
  18. 【软考必读】软考高级证书对工作的6大帮助
  19. OpenCv-C++-小案例实战-切边(二)
  20. 原神如何修改服务器,原神服务器选择攻略 新手选择官服还是渠道服好

热门文章

  1. 计算机视觉——SIFT特征提取与检索
  2. java 实现一个杨辉三角
  3. 目标检测入门知识以思考(写于2021.11)
  4. SpringBoot使用Workbook读取excel中内容
  5. java 获取token
  6. Java语言-用双精度浮点型变量计算一个圆的面积。
  7. 计算机专业方面期刊介绍--
  8. 腾讯微博android版本,腾讯微博 Android版
  9. Python基础操作_字典的遍历
  10. [蛋蛋涂鸦]沪江小D清新桌面壁纸