洛谷 P3375:【模板】KMP ← next 数组应用
【题目来源】
https://www.luogu.com.cn/problem/P3375
【题目描述】
给出两个字符串 s1 和 s2,若 s1 的区间 [l,r] 子串与 s2 完全相同,则称 s2 在 s1 中出现了,其出现位置为 l。
现在请你求出 s2 在 s1 中所有出现的位置。
定义一个字符串 s 的 border 为 s 的一个非 s 本身的子串 t,满足 t 既是 s 的前缀,又是 s 的后缀。
对于 s2,你还需要求出对于其每个前缀 s′ 的最长 border t′ 的长度。
【输入格式】
第一行为一个字符串,即为 s1。
第二行为一个字符串,即为 s2。
【输出格式】
首先输出若干行,每行一个整数,按从小到大的顺序输出 s2 在 s1 中出现的位置。
最后一行输出 ∣s2∣ 个整数,第 i 个整数表示 s2 的长度为 i 的前缀的最长 border 长度。
【输入样例】
ABABABC
ABA
【输出样例】
1
3
0 0 1
【数据范围】
对于全部的测试点,保证 1≤∣s1∣,∣s2∣≤10^6,s1,s2 中均只含大写英文字母。
【算法分析】
在 KMP 算法中,next 数组记录了模式串中每个位置之前子串的最长公共前后缀长度。
下面,给出具体分析。
一、前缀、后缀、公共前后缀、最长公共前后缀长度
(1)前缀:字符串从开头到某个位置的子串(不包括整个字符串)。
(2)后缀:字符串从某个位置到结尾的子串(不包括整个字符串)。
(3)公共前后缀:既是前缀又是后缀的子串。
(4)最长公共前后缀长度:所有公共前后缀中最长的长度。
例如,字符串 "ABABA":
前缀:"A", "AB", "ABA", "ABAB"
后缀:"A", "BA", "ABA", "BABA"
公共前后缀:"A"(长度1),"ABA"(长度3)
最长公共前后缀长度:3(对应"ABA")
二、最长公共前后缀与 next 数组的关系
在 KMP 算法中,next[i] 表示字符串前 i 个字符的最长公共前后缀长度:
(1)next[0] = -1(无匹配)
(2)next[1] = 0(单个字符无公共前后缀)
(3)next[i] 表示前 i-1 个字符的最长公共前后缀长度(i 从 2 开始)。
例如,字符串 "ABAB":
next[0] = -1
next[1] = 0
next[2] = 0("AB"无公共前后缀)
next[3] = 1("ABA"的最长公共前后缀是"A",长度 1)
next[4] = 2("ABAB"的最长公共前后缀是"AB",长度 2)
三、最长公共前后缀长度 = next[n](n 是字符串长度)。
在 KMP 算法中,next 数组的标准长度与模式串的长度相同,其索引范围从 0 到 n-1(n 为模式串长度)。但最长公共前后缀长度=next[n](n 是字符串长度),故若获取字符串的最长公共前后缀,需扩展计算到 next[n]。
for(int i=0; i<t.size(); i++) {cout<<ne[i]<<" ";
}
显然,本题的最长 border 长度,就是最长公共前后缀长度。
【算法代码】
#include <bits/stdc++.h>
using namespace std;const int maxn=1e6+5;
int ne[maxn];int main() {string s,t;cin>>s>>t;int lens=s.size();int lent=t.size();//Calculate ne[] arrayfor(int i=1,j=0; i<lent; i++) {while(j && t[i]!=t[j]) j=ne[j-1];if(t[i]==t[j]) j++;ne[i]=j;}//Execute KMP algorithmfor(int i=0,j=0; i<lens; i++) {while(j && s[i]!=t[j]) j=ne[j-1];if(s[i]==t[j]) j++;if(j==lent) {cout<<i-lent+1+1<<endl;j=ne[j-1];}}//Output ne[] arrayfor(int i=0; i<t.size(); i++) {cout<<ne[i]<<" ";}return 0;
}/*
input:
ABABABC
ABAoutput:
1
3
0 0 1
*/
【参考文献】
https://blog.csdn.net/hnjzsyjyj/article/details/153419314
https://blog.csdn.net/hnjzsyjyj/article/details/153421035
https://blog.csdn.net/hnjzsyjyj/article/details/127140892
https://www.luogu.com.cn/problem/solution/P3375