P3375 【模板】KMP

P3375 【模板】KMP

题目描述

给出两个字符串 s 1 s_1 s1 和 s 2 s_2 s2,若 s 1 s_1 s1 的区间 l , r l, r l,r 子串与 s 2 s_2 s2 完全相同,则称 s 2 s_2 s2 在 s 1 s_1 s1 中出现了,其出现位置为 l l l。

现在请你求出 s 2 s_2 s2 在 s 1 s_1 s1 中所有出现的位置。

定义一个字符串 s s s 的 border 为 s s s 的一个非 s s s 本身 的子串 t t t,满足 t t t 既是 s s s 的前缀,又是 s s s 的后缀。

对于 s 2 s_2 s2,你还需要求出对于其每个前缀 s ′ s' s′ 的最长 border t ′ t' t′ 的长度。

输入格式

第一行为一个字符串,即为 s 1 s_1 s1。

第二行为一个字符串,即为 s 2 s_2 s2。

输出格式

首先输出若干行,每行一个整数,按从小到大的顺序 输出 s 2 s_2 s2 在 s 1 s_1 s1 中出现的位置。

最后一行输出 ∣ s 2 ∣ |s_2| ∣s2∣ 个整数,第 i i i 个整数表示 s 2 s_2 s2 的长度为 i i i 的前缀的最长 border 长度。

输入输出样例 #1

输入 #1

复制代码
ABABABC
ABA

输出 #1

复制代码
1
3
0 0 1 

说明/提示

样例 1 解释

对于 s 2 s_2 s2 长度为 3 3 3 的前缀 ABA,字符串 A 既是其后缀也是其前缀,且是最长的,因此最长 border 长度为 1 1 1。

代码

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+1;
int kmp[N];//所有子串的最长相同前后缀长度 
string s1,//文本串 
	s2;//模式串 
int main(){
	//freopen("data.cpp","r",stdin);
	cin>>s1>>s2;
	memset(kmp,0,sizeof(kmp));
	for(int i=1,j=0;i<s2.length();i++){
		while(j&&s2[i]!=s2[j])j=kmp[j];
		/*
		i长字符串后第一个字符,就是i位置字符s2[i]
		不等于
		i长字符串的最长相同前后缀j长子串后第一个字符,就是j位置字符s2[j]
		回溯
		找i长字符串的最长相同前后缀的最长相同前后缀 
		*/
		if(s2[i]==s2[j])j++;//如果相等,则最长相同前后缀要+1 
		kmp[i+1]=j;//i+1字符串的相同前后缀长是j 
	}
	for(int i=0,j=0;i<s1.length();){
		if(s1[i]==s2[j])i++,j++;//对齐了,各自找下一位 
		else if(j<s2.length())//没匹配 
		if(j>0)j=kmp[j];//模式串的对齐位置跳到j长字符串的最长相同前后缀后的第一个位置j 
		else i++;
		if(j==s2.length()){cout<<i-j+1<<endl;j=kmp[j];}//匹配后输出s2在i中的位置 
	}
	for(int i=0;i<s2.length();i++)cout<<kmp[i+1]<<" ";
	return 0;
}

小结

文本串的i位置和匹配串的j位置对齐。

相关推荐
wenyq720 小时前
LeetCode 2460. Apply Operations to an Array
算法·leetcode
.格子衫.21 小时前
032动态规划之区间DP——算法备赛
算法·动态规划
不会代码的小猴1 天前
7. JSON
开发语言·c++·笔记·qt·算法·json
怪奇云呼军1 天前
知识库也会注入指令?闪电智能VoiceAgent 如何防住 Prompt Injection
人工智能·python·算法·云计算·音视频
阿里云大数据AI技术1 天前
基于 EMR Serverless Ray 实现 Qwen 模型批量推理实践
人工智能·算法·agent
Rambo.xia1 天前
为什么去马赛克算法,决定了ISP的画质上限
算法·接口隔离原则
Benny_Tang1 天前
题解:P10230 [COCI 2023/2024 #4] Lepeze
c++·算法
Geek-Chow1 天前
06 训练管线:数据如何变成权重
人工智能·算法
我变成萤火虫1 天前
反悔贪心(经典题目讲解)
c++·算法·贪心算法·stl·排序算法·反悔贪心