题目描述
给出两个字符串 s1 和 s2,若 s1 的区间 [l, r][l,r] 子串与 s2 完全相同,则称 s2 在 s1 中出现了,其出现位置为 i。
现在请你求出 s2 在 s1 中所有出现的位置。
定义一个字符串 s 的 border 为 s 的一个非 s 本身的子串 t,满足 t 既是 s 的前缀,又是 s 的后缀。
对于 s2,你还需要求出对于其每个前缀 s' 的最长 border t'的长度。
输入格式
第一行为一个字符串,即为 s1。
第二行为一个字符串,即为 s2。
输出格式
首先输出若干行,每行一个整数,按从小到大的顺序输出 s2 在 s1 中出现的位置。
最后一行输出 ∣s2∣ 个整数,第 i个整数表示 s2 的长度为 i 的前缀的最长 border 长度。
输入输出样例
输入 #1复制
ABABABC ABA
输出 #1复制
1 3 0 0 1
#include<iostream>
#include<cstring>
#define N 199999
using namespace std;
int nextval[N];
int lens1, lens2;
void get(string s2,int nextval[])
{
int j=0,k=-1;
nextval[0]=-1;
while (j<lens2)
{
if (k==-1 || s2[j]==s2[k])
{
j++;k++;
nextval[j] = k;
}
else k=nextval[k];
}
}
void kmpIndex(string s1, string s2){
get(s2,nextval);
int i = 0, j = 0;
while( i < lens1 && j < lens2){
if(j == -1 || s1[i] == s2[j]){
i++; j++;
if(j == lens2){
cout<< i-j+1<<endl;
j = nextval[j];
}
}
else j = nextval[j];
}
}
int main(){
string s1,s2;
cin>>s1>>s2;
lens1 = s1.length();
lens2 = s2.length();
kmpIndex(s1,s2);
for(int i=1; i<=lens2; i++)
cout<<nextval[i]<<" ";
return 0;
}