题目描述
如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置。
为了减少骗分的情况,接下来还要输出子串的前缀数组next。
(如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了。)
输入格式
第一行为一个字符串,即为s1
第二行为一个字符串,即为s2
输出格式
若干行,每行包含一个整数,表示s2在s1中出现的位置
接下来1行,包括length(s2)个整数,表示前缀数组next[i]的值。
输入输出样例
输入
ABABABC ABA
输出
1 3 0 0 1
说明/提示
时空限制:1000ms,128M
数据规模:
设s1长度为N,s2长度为M
对于30%的数据:N<=15,M<=5
扫描二维码关注公众号,回复:
7126443 查看本文章
对于70%的数据:N<=10000,M<=100
对于100%的数据:N<=1000000,M<=1000000
样例说明:
所以两个匹配位置为1和3,输出1、3
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 5 const int N=1e6+5; 6 int next[N]; 7 8 void getnext(char *s2){ 9 int len=strlen(s2); 10 next[0]=-1; 11 for(int i=0,j=-1;i<len;){ 12 if(j==-1||s2[i]==s2[j]) 13 next[++i]=++j; 14 else j=next[j]; 15 } 16 } 17 18 void KMP(char *s1,char *s2){ 19 getnext(s2); 20 int l1=strlen(s1),l2=strlen(s2); 21 int i=0,j=0; 22 while(j<l1){ 23 if(s2[i]==s1[j]){ 24 i++,j++; 25 if(i==l2){ 26 printf("%d\n",j-l2+1); 27 i=next[i-1]+1; 28 } 29 } 30 else{ 31 if(i==0) j++; 32 else i=next[i-1]+1; 33 } 34 } 35 } 36 37 int main(){ 38 char s1[N],s2[N]; 39 scanf("%s%s",s1,s2); 40 KMP(s1,s2); 41 int len=strlen(s2); 42 for(int i=1;i<=len;i++){ 43 if(i!=1) printf(" "); 44 printf("%d",next[i]); 45 } 46 printf("\n"); 47 }