首页 > 其他分享 >Luogu P3375 【模板】KMP字符串匹配

Luogu P3375 【模板】KMP字符串匹配

时间:2023-06-11 14:44:58浏览次数:58  
标签:include 前缀 Luogu 样例 leq nex KMP 字符串 P3375

【模板】KMP字符串匹配

题目描述

给出两个字符串 \(s_1\) 和 \(s_2\),若 \(s_1\) 的区间 \([l, r]\) 子串与 \(s_2\) 完全相同,则称 \(s_2\) 在 \(s_1\) 中出现了,其出现位置为 \(l\)。
现在请你求出 \(s_2\) 在 \(s_1\) 中所有出现的位置。

定义一个字符串 \(s\) 的 border 为 \(s\) 的一个非 \(s\) 本身的子串 \(t\),满足 \(t\) 既是 \(s\) 的前缀,又是 \(s\) 的后缀。
对于 \(s_2\),你还需要求出对于其每个前缀 \(s'\) 的最长 border \(t'\) 的长度。

输入格式

第一行为一个字符串,即为 \(s_1\)。
第二行为一个字符串,即为 \(s_2\)。

输出格式

首先输出若干行,每行一个整数,按从小到大的顺序输出 \(s_2\) 在 \(s_1\) 中出现的位置。
最后一行输出 \(|s_2|\) 个整数,第 \(i\) 个整数表示 \(s_2\) 的长度为 \(i\) 的前缀的最长 border 长度。

样例 #1

样例输入 #1

ABABABC
ABA

样例输出 #1

1
3
0 0 1

提示

样例 1 解释

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

数据规模与约定

本题采用多测试点捆绑测试,共有 3 个子任务

  • Subtask 1(30 points):\(|s_1| \leq 15\),\(|s_2| \leq 5\)。
  • Subtask 2(40 points):\(|s_1| \leq 10^4\),\(|s_2| \leq 10^2\)。
  • Subtask 3(30 points):无特殊约定。

对于全部的测试点,保证 \(1 \leq |s_1|,|s_2| \leq 10^6\),\(s_1, s_2\) 中均只含大写英文字母。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>

using namespace std;

char a[1000005], b[1000005]; 
int l1, l2, nex[1000005];

int main() {
	scanf("%s", a + 1);
	scanf("%s", b + 1);
	l1 = strlen(a + 1);
	l2 = strlen(b + 1);
	nex[0] = 1;
	for (int i = 2, j = 0; i <= l2; ++ i) {
		while (j > 0 && b[j + 1] != b[i]) {
			//如果失配,那么就不断向回跳
			//直到跳完后的子串后的下一个字符与b[i]相等或j跳到0 
			j = nex[j];
		}
		//通过自己匹配自己来得出kmp值 
		if (b[j + 1] == b[i]) j ++;
		nex[i] = j;
	}//自己与自己匹配找KMP 
	for (int i = 1, j = 0;i <= l1; ++ i) {
		while (j > 0 && b[j + 1] != a[i]) {
			j = nex[j];
		}
		if (b[j + 1] == a[i]) j ++;
		if (j == l2) {
			cout << i - l2 + 1 << endl;
			j = nex[j];
			//注意要跳到nex[j] 
		}
	}
	for (int i = 1; i <= l2; ++ i) {
		cout << nex[i] << " ";
	}
	return 0;
} 

标签:include,前缀,Luogu,样例,leq,nex,KMP,字符串,P3375
From: https://www.cnblogs.com/jueqingfeng/p/17472938.html

相关文章

  • Luogu P3167 [CQOI2014]通配符匹配
    [CQOI2014]通配符匹配题目描述几乎所有操作系统的命令行界面(CLI)中都支持文件名的通配符匹配以方便用户。最常见的通配符有两个,一个是星号(”“'),可以匹配0个及以上的任意字符:另一个是问号(”?“),可以匹配恰好一个任意字符。现在需要你编写一个程序,对于给定的文件名列表和一个包......
  • Luogu P4591 [TJOI2018]碱基序列
    [TJOI2018]碱基序列题目描述小豆参加了生物实验室。在实验室里,他主要研究蛋白质。他现在研究的蛋白质是由\(k\)个氨基酸按一定顺序构成的。每一个氨基酸都可能有\(a\)种碱基序列\(s_{i,j}\)构成。现在小豆有一个碱基串\(s\),小豆想知道在这个碱基上都多少中不同的组合方式可能得......
  • Luogu P4159 [SCOI2009] 迷路
    [SCOI2009]迷路题目背景windy在有向图中迷路了。题目描述该有向图有\(n\)个节点,节点从\(1\)至\(n\)编号,windy从节点\(1\)出发,他必须恰好在\(t\)时刻到达节点\(n\)。现在给出该有向图,你能告诉windy总共有多少种不同的路径吗?答案对\(2009\)取模。注意:windy......
  • Luogu P1939 【模板】矩阵加速(数列)
    【模板】矩阵加速(数列)题目描述已知一个数列\(a\),它满足:\[a_x=\begin{cases}1&x\in\{1,2,3\}\\a_{x-1}+a_{x-3}&x\geq4\end{cases}\]求\(a\)数列的第\(n\)项对\(10^9+7\)取余的值。输入格式第一行一个整数\(T\),表示询问个数。以下\(T\)行,每行一个正......
  • Luogu P3390 【模板】矩阵快速幂
    【模板】矩阵快速幂题目背景一个\(m\timesn\)的矩阵是一个由\(m\)行\(n\)列元素排列成的矩形阵列。即形如\[A=\begin{bmatrix}a_{11}&a_{12}&\cdots&a_{1n}\\a_{21}&a_{22}&\cdots&a_{2n}\\\vdots&\vdots&\ddots&......
  • Luogu B2105 矩阵乘法(模板)
    矩阵乘法题目描述计算两个矩阵的乘法。\(n\timesm\)阶的矩阵\(A\)乘以\(m\timesk\)阶的矩阵\(B\)得到的矩阵\(C\)是\(n\timesk\)阶的,且\(C[i][j]=A[i][0]\timesB[0][j]+A[i][1]\timesB[1][j]+\)……\(+A[i][m-1]\timesB[m-1][j](C[i][j]\)表示\(C\)......
  • Luogu P4219 [BJOI2014]大融合
    [BJOI2014]大融合题目描述小强要在\(N\)个孤立的星球上建立起一套通信系统。这套通信系统就是连接\(N\)个点的一个树。这个树的边是一条一条添加上去的。在某个时刻,一条边的负载就是它所在的当前能够联通的树上路过它的简单路径的数量。例如,在上图中,现在一共有了\(5\)......
  • 算法基础(一):串匹配问题(BF,KMP算法)
    好家伙,学算法,这篇看完,如果没有学会KMP算法,麻烦给我点踩希望你能拿起纸和笔,一边阅读一边思考,看完这篇文章大概需要(20分钟的时间) 我们学这个算法是为了解决串匹配的问题那什么是串匹配?举个例子:我要在"彭于晏吴彦祖"这段字符串中找到"吴彦祖"字符串这就是串匹配......
  • Luogu P4577 [FJOI2018] 领导集团问题
    [FJOI2018]领导集团问题题目描述一个公司的组织领导架构可以用一棵领导树来表示。公司的每个成员对应于树中一个结点\(v_i\),且每个成员都有响应的级别\(w_i\)。越高层的领导,其级别值\(w_i\)越小。树中任何两个结点之间有边相连,则表示与结点相应的两个成员属于同一部门。领......
  • Luogu P5446 [THUPC2018] 绿绿和串串
    根据题目能发现一个性质,设转化前的字符串为\(s\),转化后的字符串为\(s'\),则\(s'_{|s|}\)为\(s'\)的中心,即\(s'_{|s|}\)求出来的回文串左边界为\(1\)右边界为\(|s'|\)找出这个性质就挺简单了,考虑先对给出的\(S\)用\(\text{manacher}\)求出每个节点\(i\)对应的左边......