感觉这道题非常有意思,学的过程中觉得及难,学完之后觉得及简单,看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字符串的更多相关文章

  1. 831. KMP字符串(模板)

    给定一个模式串S,以及一个模板串P,所有字符串中只包含大小写英文字母以及阿拉伯数字. 模板串P在模式串S中多次作为子串出现. 求出模板串P在模式串S中所有出现的位置的起始下标. 输入格式 第一行输入整 ...

  2. AcWing 831. KMP字符串(模板)

    给定一个模式串S,以及一个模板串P,所有字符串中只包含大小写英文字母以及阿拉伯数字. 模板串P在模式串S中多次作为子串出现. 求出模板串P在模式串S中所有出现的位置的起始下标. 输入格式 第一行输入整 ...

  3. AcWing 831. KMP字符串

    #include <iostream> using namespace std; , M = ; int n, m; int ne[N];//ne[i] : 以i为结尾的部分匹配的值 ch ...

  4. 831. KMP字符串

    给定一个模式串S,以及一个模板串P,所有字符串中只包含大小写英文字母以及阿拉伯数字. 模板串P在模式串S中多次作为子串出现. 求出模板串P在模式串S中所有出现的位置的起始下标. 输入格式 第一行输入整 ...

  5. KMP字符串模式匹配详解(转)

    来自CSDN     A_B_C_ABC 网友 KMP字符串模式匹配通俗点说就是一种在一个字符串中定位另一个串的高效算法.简单匹配算法的时间复杂度为O(m*n);KMP匹配算法.可以证明它的时间复杂度 ...

  6. BM和KMP字符串匹配算法学习

    BM和KMP字符串匹配算法学习 分类: 研究与学习 字符串匹配BM(Boyer-Moore)算法学习心得 http://www.cnblogs.com/a180285/archive/2011/12/ ...

  7. KMP字符串模式匹配详解(zz)

    刚看到位兄弟也贴了份KMP算法说明,但本人觉得说的不是很详细,当初我在看这个算法的时候也看的头晕昏昏的,我贴的这份也是网上找的.且听详细分解: KMP字符串模式匹配详解 来自CSDN     A_B_ ...

  8. KMP字符串模式匹配详解

    KMP字符串模式匹配详解 http://www.cppblog.com/oosky/archive/2006/07/06/9486.html

  9. KMP字符串模式匹配学习笔记

    KMP算法实验 1.编程计算模式串(子串)的next值.2.利用KMP算法在主串中找到模式串的位置. 参考代码:---------int getNexlVal( char * s,  int j)// ...

随机推荐

  1. java中内部类中还有内部类请给实例!

    2.当内部类中还有一个内部类,下面给出了一个实例.[新手可忽略不影响继续学习](以下多出代码, 用蓝色标记)例2.2:class ShellMark_to_win {    int shell_x = ...

  2. 多态,动态方法调度(dynamic method dispatch)?

    8.多态Polymorphism,向上转型Upcasting,动态方法调度(dynamic method dispatch) 什么叫多态?简言之,马 克 - t o - w i n:就是父类引用指向子 ...

  3. SQL语句总结---表操作

    https://blog.csdn.net/hallomrzhang/article/details/85010014 表的操作 1.查看表结构 desc 表名 2.创建表结构的语法 create t ...

  4. HTML表格CSS美化

    效果展示 style.css html{ width: 100%; height: 100%; overflow: hidden;}body{ width: 100%; height: 100%; f ...

  5. Java 将Map按Value值降序排列

    1 /** 2 * 将集合按照降序排列-FLOAT 3 * @param nowPartTwoData 4 * @return 5 */ 6 private static List<Map.En ...

  6. Virtual Function(虚函数)in c++

    Virtual Function(虚函数)in c++ 用法: virtual void log() { std::cout << "hello world!" < ...

  7. Mxnet速查_CPU和GPU的mnist预测训练_模型导出_模型导入再预测_导出onnx并预测

    需要做点什么 方便广大烟酒生研究生.人工智障炼丹师算法工程师快速使用mxnet,所以特写此文章,默认使用者已有基本的深度学习概念.数据集概念. 系统环境 python 3.7.4 mxnet 1.9. ...

  8. Windows中Nginx配置nginx.conf不生效解决方法

    转:https://lucifer.blog.csdn.net/article/details/83860644?utm_medium=distribute.pc_relevant.none-task ...

  9. IDEA小技巧:Debug条件断点

    今天给大家分享一个IDEA调试过程中的一个小技巧. 先来说说场景,你有没有碰到类似的情况,一个循环结构里,中间某一个情况可能会出错.比如下面的代码结果中,可能执行到第27次的时候,会出现问题. for ...

  10. [UE][虚幻]创建默认媒体打包资源路径

    **创建默认媒体打包资源路径** **个人笔记**   **翻阅官方资料,实践出来的!**   **转载,"借鉴",重写...其他行为必须标明出处!!!** UE 官方默认有一个专 ...