洛谷P3375 [模板]KMP字符串匹配
能看的模板还是看这里。
题目描述
如题,给出两个字符串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
代码:
最新提交:
模式串为p,主串为s,代码中写反了。对p求fail。
1 // luogu-judger-enable-o2 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 const int N=1e6+5; 6 7 int fail[N]; 8 char s[N],p[N]; 9 10 void Get_Fail() 11 { 12 fail[0]=fail[1]=0; 13 int l=strlen(s+1); 14 for(int j=0,i=2; i<=l; ++i) 15 { 16 while(j && s[i]!=s[j+1]) j=fail[j]; 17 fail[i]= s[i]==s[j+1]?++j:0; 18 } 19 } 20 void KMP() 21 { 22 int l=strlen(p+1),ls=strlen(s+1); 23 for(int i=1,j=0; i<=l; ++i) 24 { 25 while(j && p[i]!=s[j+1]) j=fail[j]; 26 if(p[i]==s[j+1]) ++j; 27 if(j==ls) printf("%d\n",i-ls+1); 28 } 29 for(int i=1; i<=ls; ++i) 30 printf("%d ",fail[i]); 31 } 32 33 int main() 34 { 35 scanf("%s%s",p+1,s+1); 36 Get_Fail(); 37 KMP(); 38 39 return 0; 40 }
旧的:
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 char s1[1000020],s2[1020]; 5 int len1,len2,fai[1020]; 6 void getfail() 7 { 8 fai[0]=fai[1]=0; 9 for(int i=1;i<len2;i++) 10 { 11 int j=fai[i]; 12 while(j&&s2[i]!=s2[j]) j=fai[j]; 13 fai[i+1]= s2[i]==s2[j] ? j+1 : 0; 14 } 15 } 16 void kmp() 17 { 18 int j=0; 19 for(int i=0;i<len1;i++) 20 { 21 while(j&&s1[i]!=s2[j]) j=fai[j]; 22 if(s1[i]==s2[j]) ++j; 23 if(j==len2) 24 printf("%d\n",i-len2+2); 25 } 26 } 27 int main() 28 { 29 scanf("%s",s1); 30 scanf("%s",s2); 31 len1=strlen(s1); 32 len2=strlen(s2); 33 getfail(); 34 kmp(); 35 for(int i=1;i<=len2;i++) 36 printf("%d ",fai[i]); 37 return 0; 38 }
[2018.4.4] :更新后的模板
1 #include <cstdio> 2 #include <cstring> 3 const int N=1e6+5; 4 5 int len,fail[N]; 6 char p[N],s[N]; 7 8 void Get_fail() 9 { 10 fail[0]=0; 11 for(int i=1,j; i<len; ++i) 12 { 13 j=fail[i]; 14 while(s[i]!=s[j]&&j) j=fail[j]; 15 fail[i+1]=s[i]==s[j]?j+1:0; 16 } 17 } 18 void KMP() 19 { 20 for(int i=0,j=0,l=strlen(p); i<l; ++i) 21 { 22 while(p[i]!=s[j]&&j) j=fail[j]; 23 if(p[i]==s[j]) ++j; 24 if(j==len) printf("%d\n",i-j+2); 25 } 26 for(int i=1; i<=len; ++i) printf("%d ",fail[i]); 27 } 28 29 int main() 30 { 31 scanf("%s%s",p,s), len=strlen(s), Get_fail(), KMP(); 32 return 0; 33 }
------------------------------------------------------------------------------------------------------------------------
很久以前的奇怪但现在依旧成立的签名
attack is our red sun $$\color{red}{\boxed{\color{red}{attack\ is\ our\ red\ sun}}}$$ ------------------------------------------------------------------------------------------------------------------------
很久以前的奇怪但现在依旧成立的签名
attack is our red sun $$\color{red}{\boxed{\color{red}{attack\ is\ our\ red\ sun}}}$$ ------------------------------------------------------------------------------------------------------------------------