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)// ...
随机推荐
- Linux 0.11源码阅读笔记-总结
总结 Linux 0.11主要包含文件管理和进程管理两个部分.进程管理包括内存管理.进程管理.进程间通信模块.文件管理包含磁盘文件系统,打开文件内存数据.磁盘文件系统包括空闲磁盘块管理,文件数据块的管 ...
- MyEclipse如何刷新项目
第一种:选中项目,点右键Refresh即可, 第二种:选择project->clean,选中所要编译得项目,点ok即可
- Uncaught TypeError: document.getElementsById is not a function
今天博主终于开始攻关javascript(俗称js)了,不过要注意了,它和java可是一丁点关系都没有,就像老婆饼和老婆一样. 下面就让我们来讨论一下博主这次犯下的低级错误吧 一.背景(解决方法在文末 ...
- WebSocket学习笔记
参考文章链接:http://www.ruanyifeng.com/blog/2017/05/websocket.html 简单示例:https://www.yiibai.com/websocket/p ...
- MySQL安装配置教程(超级详细)
一. 下载MySQL Mysql官网下载地址:https://downloads.mysql.com/archives/installer/ 1. 选择要安装的版本,本篇文章选择的是5.7.31版本, ...
- ICMP TYPE CODE 对应表
下载ping程序源代码等信息,可以在这里下载 [root@ht8 network-scripts]# ping -V ping utility, iputils-s20160308 //ping实用程 ...
- metasploit基本命令
一.核心命令 ? 帮助命令 banner 显示一个真棒metasploite横幅 cd 更改当前的工作目 color 切换颜色 connect 连接与主机通信 exit 退出控制台 get 获取特定于 ...
- 高精度减法(C++实现)
高精度减法 简介 用于计算含有超过一般变量存放不下的非负整数 高精度加法这个过程是模拟的小学竖式减法计算 注:在本文中,我们默认输入的第一个数为被减数,且被减数大于减数 原理基本上与高精度加法相同,仅 ...
- 缓存中间件-Redis(一)
1.Redis介绍 REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的 key-value 存储系统,是跨平台的非关系型数据库,Red ...
- C#+Access 员工信息管理--简单的增删改查操作和.ini配置文件的读写操作。
1.本程序的使用的语言是C#,数据库是Access2003.主要是对员工信息进行简单的增删改查操作和对.ini配置文件的读写操作. 2.代码运行效果如下: 功能比较简单.其中在得到查询结果后,在查询结 ...