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)// ...
随机推荐
- 「进阶篇」Vue Router 核心原理解析
前言 此篇为进阶篇,希望读者有 Vue.js,Vue Router 的使用经验,并对 Vue.js 核心原理有简单了解: 不会大篇幅手撕源码,会贴最核心的源码,对应的官方仓库源码地址会放到超上,可以配 ...
- jupyter notebook 调用.py文件
方法1.利用 %run xx.py 直接运行得出结果. 方法2:利用 %load xx.py 载入代码再点击Run运行,这种方法的好处是可以方便修改代码. 说明: Jupyter Notebook中以 ...
- zabbix使用自带模板监控MySQL
监控mysql不能直接使用zabbix自带模板,还需要到被监控的mysql客户端做配置. 1.在zabbix web配置步骤如下图: 2.配置完之后去看mysql主机监控项的时候看到mysql的监 ...
- docker容器编排原来这么丝滑~
前言: 请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i 概念介绍: Docker Docker 这个东西所扮演的角色,容易理解,它是一个容器引擎,也就是说实际上我们的容器最终是由Docker ...
- linux find命令 -mtime参数 根据修改时间查找文件
命令:find 搜索路径 -mtime n 主要说明n的含义: 例: n=5 "5"指的是前 5~6 天那一天修改的文件 n=-5 "-5"指的是 5 天内修改 ...
- Postman大势已去
作为一名前端,日常开发过程中除了写业务代码,前后端联调更是重要的一环.但这一环却往往是整个开发中最繁琐也最累人的一环.任谁都想早点下班,然而提升联调效率并不是个纯技术相关的问题,而是需要有良好工作流程 ...
- 《手写Mybatis》第4章:Mapper XML的解析和注册使用
作者:小傅哥 系列:https://bugstack.cn/md/spring/develop-mybatis/2022-03-20-%E7%AC%AC1%E7%AB%A0%EF%BC%9A%E5%B ...
- Nuxt.js(二、解决首屏速度与SEO)
Nuxt.js(二.解决首屏速度与SEO) 1.普通的Vue SPA初始化加载速度很慢 在传统的web应用中,当用户请求一个页面时,服务器直接返回一个html文件,浏览器直接渲染出来.但是,在vue应 ...
- GET sql注入
靶机地址:192.168.43.156 攻击机地址:192.168.43.89 一.AppScan检查靶机sql漏洞 二.使用sqlmap利用SQL注入漏洞 1.sqlmap -u " ht ...
- what 的页面制作
1. html结构 <!-- section: what we do --> <section id="what" class="bg-light py ...