ACW:831. KMP字符串
感觉这道题非常有意思,学的过程中觉得及难,学完之后觉得及简单,看y总的视频没有看懂。。。,因此自己找了一篇博文理解并完成题目。
import java.io.*;
/**
* @author admin
* @Date 2021/11/11 20:07
* @Description 思路主要参考: https://www.cnblogs.com/dusf/p/kmp.html ,
* 理解的前提为:明白如果abcdabce在e的时候匹配不成功不用从第0个a(为统一,下标从0开始)开始匹配,
* 而是直接从重复的abc后的一个元素d开始匹配即可,因为前后有重复的abc ,
* 假设已经知道e不匹配要跳回的元素是d的话(next数组),那么这就是一个不断匹配的过程
* 即:不成功就跳回到前一个重复的串的后一个元素,匹配。。。成功就跳回到前一个重复的串的后一个元素,匹配。。。一直重复下去
* 明白了这点下一步就是看跳回哪个下标,跳回的下标用next数组存放,因此next数组存放的就是:
* //next[k]表示的是第k个如果不匹配应该跳到哪个点,从第0个数开始----k点之前哦 ---也就是说第k点之前有多少个重复的!!!
* //比如a, b, c, a, b, d 对应的next数组为
* // -1, 0, 0, 0, 1, 2,
* //这样正好匹配当a不匹配时只能跳回第0个数a开始匹配,
* // 当b不能匹配时可以确保第二个a已经匹配,因此可以直接跳回第1个数(第0个b)开始匹配
* //也是因此第0个数不用判断(直接给-1,标识应该移动母串而不是子串了,因为第0个数都不匹配),最后一个数也是不用参与判断的(原因见上5行注释)
*
* 明白了上述过程后重点就是计算next数组,在计算next数组时候会发现一件事
* :kmp就是:比较字母串是否匹配, 不匹配就往next数组指定的下标跳
* :计算next数组就是: 比较当前字符串的后面与前面是否匹配 , 不匹配就?
* 应该已经有一些感觉了,不匹配就和比较的过程一样呗,往next数组指定的下标跳呗~!!!!!!!!!!最关键的点结束了
* (跳的时候不用太担心边界,是因为next数组存放的是一定是往前跳的,往后跳是不可能的)
* 这两个步骤就是重复的呀!!!!,而且最难理解的就在于k=next[k],即往前一个可以跳的地方跳再重新匹配这个过程
* 之后的一些细节应该不太难了
* @return
* @param
*/
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter BufferedWriter = new BufferedWriter(new OutputStreamWriter(System.out));
int n = Integer.parseInt(bufferedReader.readLine());
String s1 = bufferedReader.readLine();
int m = Integer.parseInt(bufferedReader.readLine());
String s2 = bufferedReader.readLine();
char[] p = s1.toCharArray();
char[] s = s2.toCharArray();
int[] next = ne(p);
//计算完ne数组下面计算的是kmp的输出
/*
这里的写法和求next数组基本一模一样,但是需要注意的是第0个数和最后一个数需要参与比较,
因此改动:1.j=-1开始,2.while (j <= s.length - 1)中的“=”;
然后由于求的是所有匹配结果,因此在匹配后加入特判k == p.length - 1,为true时
表示匹配成功,此时应该输出结果,以及当成此节点匹配失败重新开始匹配值(k = next[k];)
*/
int k = -1, j = -1;
while (j <= s.length - 1) {
if (k == -1 || s[j] == p[k]) {
if (k == p.length - 1) {
BufferedWriter.write(j - k + " ");
k = next[k];
continue;
}
k++;
j++;
}else {
k = next[k];
}
}
bufferedReader.close();
BufferedWriter.flush();
BufferedWriter.close();
}
private static int[] ne(char[] p) {
//next[k]表示的是k点之前有多少个重复的,从第0个数开始
//比如a, b, c, a, b, d 对应的next数组为
// -1, 0, 0, 0, 1, 2,
//这样正好匹配当a不匹配时只能跳回第0个数a开始匹配,
// 当b不能匹配时可以确保第二个a已经匹配,因此可以直接跳回第1个数(第0个b)开始匹配
//也是因此第0个数不用判断(直接给-1,标识应该移动母串而不是子串了,因为第0个数都不匹配),最后一个数也是不用参与判断的(原因见上5行注释)
int[] next = new int[p.length];
next[0] = -1;
int k = -1, j = 0;
while (j < p.length - 1) {
if (k == -1 || p[j] == p[k]) {
k++;
j++;
next[j] = k;
} else {
k = next[k];
}
}
return next;
}
}
ACW:831. KMP字符串的更多相关文章
- 831. KMP字符串(模板)
给定一个模式串S,以及一个模板串P,所有字符串中只包含大小写英文字母以及阿拉伯数字. 模板串P在模式串S中多次作为子串出现. 求出模板串P在模式串S中所有出现的位置的起始下标. 输入格式 第一行输入整 ...
- AcWing 831. KMP字符串(模板)
给定一个模式串S,以及一个模板串P,所有字符串中只包含大小写英文字母以及阿拉伯数字. 模板串P在模式串S中多次作为子串出现. 求出模板串P在模式串S中所有出现的位置的起始下标. 输入格式 第一行输入整 ...
- AcWing 831. KMP字符串
#include <iostream> using namespace std; , M = ; int n, m; int ne[N];//ne[i] : 以i为结尾的部分匹配的值 ch ...
- 831. KMP字符串
给定一个模式串S,以及一个模板串P,所有字符串中只包含大小写英文字母以及阿拉伯数字. 模板串P在模式串S中多次作为子串出现. 求出模板串P在模式串S中所有出现的位置的起始下标. 输入格式 第一行输入整 ...
- KMP字符串模式匹配详解(转)
来自CSDN A_B_C_ABC 网友 KMP字符串模式匹配通俗点说就是一种在一个字符串中定位另一个串的高效算法.简单匹配算法的时间复杂度为O(m*n);KMP匹配算法.可以证明它的时间复杂度 ...
- BM和KMP字符串匹配算法学习
BM和KMP字符串匹配算法学习 分类: 研究与学习 字符串匹配BM(Boyer-Moore)算法学习心得 http://www.cnblogs.com/a180285/archive/2011/12/ ...
- KMP字符串模式匹配详解(zz)
刚看到位兄弟也贴了份KMP算法说明,但本人觉得说的不是很详细,当初我在看这个算法的时候也看的头晕昏昏的,我贴的这份也是网上找的.且听详细分解: KMP字符串模式匹配详解 来自CSDN A_B_ ...
- KMP字符串模式匹配详解
KMP字符串模式匹配详解 http://www.cppblog.com/oosky/archive/2006/07/06/9486.html
- KMP字符串模式匹配学习笔记
KMP算法实验 1.编程计算模式串(子串)的next值.2.利用KMP算法在主串中找到模式串的位置. 参考代码:---------int getNexlVal( char * s, int j)// ...
随机推荐
- java1.7之后的比较器特别之处
在jdk1.7环境下使用Collectons.sort()方法: 比如:Collections.sort(list, new Comparator<Integer>()); 就可能会出现异 ...
- 截取url传值
// 页面传值 subStr(url) { var obj = {}; var str = url.split('?')[1]; var str2 = str.split('&'); cons ...
- TINY语言采用递归下降分析法编写语法分析程序
目录 自顶向下分析方法 TINY文法 消左提左.构造first follow 基本思想 python构造源码 运行结果 参考来源:聊聊编译原理(二) - 语法分析 自顶向下分析方法 自顶向下分析方法: ...
- Python入门-第一行代码到多行代码
不管学啥语言,开始的第一行代码都是: print("hello word") 回车之后,就代表你正式进入代码的世界! 如果报错,恭喜你获得第一个书写bug,请检查单词拼写,双引号, ...
- 如何在 Java 中实现无向环和有向环的检测
无向环 一个含有环的无向图如下所示,其中有两个环,分别是 0-2-1-0 和 2-3-4-2: 要检测无向图中的环,可以使用深度优先搜索.假设从顶点 0 出发,再走到相邻的顶点 2,接着走到顶点 2 ...
- 在原有mysql机器上增加一台实例
采用的是yum install mysql-community-server yum方式安装mysql(社区版) 文章基础上新加一个mysql实例. 这个完全可以直接实战上应用,只要规划好即可 服务器 ...
- 帝国CMS实现栏目批量修改:是否生成
帝国cms实现栏目批量修改 是否生成:不生成栏目页, 不生成内容页, 不生成JS调用, 标签不调用的修改方本文关键字词:栏目批量设置第一步./e/admin/SetMoreClass.php中查找: ...
- linux修改静态ip
1.修改配置文件 vi /etc/sysconfig/network-scripts/ifcfg-ens32 bootproto:设置为静态 onboot:开机自启 ipaddr:ip地址 netma ...
- [python][flask] Jinja 模板入门
Flask 和 Django 附带了强大的 Jinja 模板语言. 对于之前没有接触过模板语言的人来说,这类语言基本上就是包含一些变量,当准备渲染呈现 HTML 时,它们会被实际的值替换. 这些变量放 ...
- OpenHarmony 3.1 Beta 版本关键特性解析——ArkUI canvas组件
(以下内容来自开发者分享,不代表 OpenHarmony 项目群工作委员会观点) 江英杰 华为技术有限公司 canvas 是 ArkUI 开发框架里的画布组件,常用于自定义绘制图形.因为其轻量.灵活. ...