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位置对齐。

相关推荐
aaaameliaaa2 小时前
字符函数和字符串函数
c语言·笔记·算法
城管不管3 小时前
ReAct、Plan-and-Execute、Reflection 三大智能 Agent 范式核心区别
java·人工智能·算法·spring·ai·动态规划
月疯3 小时前
二分法算法(水平等分图形面积)
算法
豆瓣鸡4 小时前
算法日记 - Day3
java·开发语言·算法
白白白小纯4 小时前
算法篇—反转链表
c语言·数据结构·算法·leetcode
Achou.Wang4 小时前
深入理解go语言-第5章 并发编程——Go的灵魂
大数据·算法·golang
The Chosen One9854 小时前
高进度算法模板速记(待完善)
java·前端·算法
土豆.exe7 小时前
Fastjson2 2.0.53 哈希碰撞 RCE:从原理到三种打法
算法·哈希算法
黄河123长江7 小时前
有限Abel群的结构()
算法
Jerry8 小时前
LeetCode 92. 反转链表 II
算法