题目描述
如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置。
为了减少骗分的情况,接下来还要输出子串的前缀数组next。如果你不知道这是什么意思也不要问,去百度搜[kmp算法]学习一下就知道了。
输入输出格式
输入格式:第一行为一个字符串,即为s1(仅包含大写字母)
第二行为一个字符串,即为s2(仅包含大写字母)
输出格式:若干行,每行包含一个整数,表示s2在s1中出现的位置
接下来1行,包括length(s2)个整数,表示前缀数组next[i]的值。
输入输出样例
输入样例#1:
ABABABC ABA
输出样例#1:
1 3 0 0 1
说明
时空限制:1000ms,128M
数据规模:
设s1长度为N,s2长度为M
对于30%的数据:N<=15,M<=5
对于70%的数据:N<=10000,M<=100
对于100%的数据:N<=1000000,M<=1000
样例说明:
所以两个匹配位置为1和3,输出1、3
code
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 5 using namespace std; 6 7 const int N = 10000100; 8 int p[N],n,m; // p最长的公共前后缀 9 char A[N],B[N]; // A主串,B模式串 10 11 void get_p() { 12 p[1] = 0; 13 for (int i=2; i<=m; ++i) { 14 int j = p[i-1]; 15 while (j && B[i]!=B[j+1]) j = p[j]; 16 if (B[i] == B[j+1]) j++; 17 p[i] = j; 18 } 19 } 20 void kmp() { 21 int j = 0; 22 for (int i=1; i<=n; ++i) { 23 while (j && A[i]!=B[j+1]) j = p[j]; 24 if (A[i]==B[j+1]) j++; 25 if (j==m) printf("%d ",i-m+1); 26 } 27 } 28 int main () { 29 scanf("%s",A+1); 30 scanf("%s",B+1); 31 n = strlen (A+1); 32 m = strlen(B+1); 33 get_p(); 34 kmp(); 35 for (int i=1; i<=m; ++i) 36 printf("%d ",p[i]); 37 return 0; 38 }
以前的代码
1 #include<cstdio> 2 #include<cstring> 3 char a[1000100],b[1010]; 4 int s1,s2; 5 int p[1010]; 6 void init() 7 { 8 int j=0; 9 p[0]=0; 10 for(int i=1;i<s2;i++) 11 { 12 while(j>0&&b[j]!=b[i]) j=p[j-1]; 13 if(b[j]==b[i]) j++; 14 p[i]=j; 15 } 16 } 17 void kmp() 18 { 19 int j=0; 20 for(int i=0;i<s1;i++) 21 { 22 if(j>0&&b[j]!=a[i]) j=p[j-1]; 23 if(b[j]==a[i]) j++; 24 if(j==s2) printf("%d ",i+1-s2+1); 25 } 26 } 27 int main() 28 { 29 scanf("%s%s",a,b); 30 s1=strlen(a); 31 s2=strlen(b); 32 init(); 33 kmp(); 34 for(int i=0;i<s2;i++) 35 printf("%d ",p[i]); 36 return 0; 37 }