题目描述
如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置。
为了减少骗分的情况,接下来还要输出子串的前缀数组next。
(如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了。)
输入输出格式
输入格式:
第一行为一个字符串,即为s1
第二行为一个字符串,即为s2
输出格式:
若干行,每行包含一个整数,表示s2在s1中出现的位置
接下来1行,包括length(s2)个整数,表示前缀数组next[i]的值。
思路
KMP很重要的。
一开始我next数组半天没搞懂。。。
其实就是自己与自己匹配。
每一次找一个相同的字母,不停地累上去,就可以求出next数组。
然后匹配,跟着数组跳即可。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1e6+7;
int next[maxn];
char s2[maxn],s1[maxn];
void spawn_next(char* st)
{
int l=strlen(st),k=0;
next[0]=-1;
for(int i=0; i<l; i++)
{
k=next[i];
while(k!=-1&&st[i]!=st[k]) k=next[k];
next[i+1]=++k;
}
}
int match(char* st,char* s)
{
int l1=strlen(st),l2=strlen(s);
int k=0;
for(int i=0; i<l1; i++)
{
while(k!=-1&&st[i]!=s[k]) k=next[k];
if(st[i]==s[k]) k++;
if(k==l2) return i-l2+1;
}
}
int kmp(char* st,char* s)
{
spawn_next(st); return match(st,s);
}
int main()
{
scanf("%s%s",s1,s2);
int ass=kmp(s1,s2)+1;
printf("%d",ass);
}