题目描述
给出两个字符串 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
#include<bits/stdc++.h>
using namespace std;
const int N = 1000005;
string t, s;
int nxt[N], a, b;
void getNext()
{
int slen = s.length();
int j = 0;
int k = -1;
nxt[0] = -1;
while(j < slen){
if(k == -1 || s[j] == s[k]){
++k;
++j;
nxt[j] = k;
}
else{
k = nxt[k];
}
}
}
void kmp()
{
int i = 0;
int j = 0;
int tlen = t.length();
int slen = s.length();
while(i < tlen){
if(j == -1 || t[i] == s[j]){
i++;
j++;
}
else{
j = nxt[j];
}
if(j == slen){
cout << i - slen + 1 << endl;
j = nxt[j];
}
}
}
int main()
{
cin >> t;
cin >> s;
getNext();
kmp();
for(int i = 1; i <= s.length(); i++)
cout << nxt[i] << " ";
return 0;
}