关于kmp,实际上算是一种比较抽象的概念,其是在暴力算法的基础上所进行优化。在起初,一些匹配字符串上我就会常常去使用暴力枚举的方法。例如有很经典的一道例题。
Findalloccurrences of the stringwordin thestringtext.
Input
Thefirstline containsthe stringtext,the secondline containsthe stringword. The length of each string is greater than 0andless than50000, the strings containonly latin letters.
Output
Print theposition numbers fromwhich thestringwordstarts in astringtextin ascending order.As is usually in programming, the string positions start fromzero.
Input Output ababbababa aba 0 5 7
暴力枚举顾名思义就是对母串和子串挨个匹配,但在匹配失败时会从头开始。
#include "stdio.h"
#include "string.h"
int main(){
char s[50001],p[50001];
scanf("%s %s",s,p);
int m,n;
m=strlen(s);
n=strlen(p);
int i=0,j=0;
int temp[50001],k=0,amount;
while(i<m){
while(j<n){
if(s[i]==p[j]){
i++;
j++;
}
else{
break;
}
}
if(j==n){
temp[k]=i-n;
k++;
}
i=i-j+1;
j=0;
}
for(i=0;i<k;i++){
printf("%d ",temp[i]);
}
return 0;
}
而kmp,就是一种巧妙的优化方法,其核心就是next数组,其本质就是其数组的每个元素表示的是以该元素结尾的字符串的最大匹配前后字符子串的长度值 ,可以在匹配失败时适当的回退,从而提升效率。附上我用kmp优化过的代码。
#include <iostream>
#include<cstring>
using namespace std;
int main(){
char s[50001],p[50001];
int next[50001];
cin>>s+1>>p+1;
int i,j;
int m=strlen(s+1);
int n=strlen(p+1);
for(i=2,j=0;i<=n;i++){
while(j&&p[i]!=p[j+1]){ //确定next数组
j=next[j];
}
if(p[i]==p[j+1]){
j++;
}
next[i]=j;
}
for(i=1,j=0;i<=m;i++){
while(j&&s[i]!=p[j+1]){ //开始匹配
j=next[j];
}
if(s[i]==p[j+1]){
j++;
}
if(j==n){
printf("%d ",i-n); //输出结果
j=next[j];
}
}
return 0;
}