AcWing 831. KMP字符串--java注释
原题链接
简单
作者:
OneDay1
,
2021-02-20 14:18:51
,
所有人可见
,
阅读 213
import java.util.*;
import java.io.*;
//下标为什么从1开始,简化代码的复杂度;
public class Main{
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
// 对模式串p进行操作
int n = Integer.parseInt(br.readLine());
char[] p = new char[n+1];
// 将输入的字符保存到缓冲区
String pstr = br.readLine();
for(int i = 1; i <=n;i++){
// 取出的字符串下标-1;
p[i] = pstr.charAt(i-1);
}
// 对模板串进行操作
int m = Integer.parseInt(br.readLine());
char[] s = new char[m+1];
String sstr = br.readLine();
for(int i = 1;i <= m;i++){
s[i] = sstr.charAt(i-1);
}
// 实现next数组
int[] next = new int[n+1];
//next[1] = 0;
for(int i = 2,j =0; i<= n;i++){
// 如果j回退到0或者i位置元素与j+1位置的元素不相同,那么执行回退操作,
//j退回next[i]处,即前缀与后缀相同的区间最后元素位置
while(j !=0 && p[i] != p[j+1]) j = next[j];
// 如果i与j+1相同,那么移动j向后匹配
if(p[i] == p[j+1]) j++;
// p[1,j] = p[i-j+1,i];前缀与后缀相同;i表示终点
next[i] = j;
}
// kmp匹配过程,遍历s模板每个元素
for(int i =1, j =0; i<=m; i++ ){
// 如果j回退到0或者i位置元素与j+1位置的元素不相同,那么执行回退操作,
//j退回next[i]处,即前缀与后缀相同的区间最后元素位置
while(j != 0 && s[i] != p[j+1]) j = next[j];
if(s[i] == p[j+1]) j++;
// 如果匹配成功
if(j ==n){
// 输出匹配元素在s模板中的起始位置
bw.write(i-n+" ");
// 继续匹配;
j = next[j];
}
}
bw.flush();
br.close();
bw.close();
}
}