什么是暴力匹配?
规定i是主串S的下标,j是模式T的下标。现在假设现在主串S匹配到 i 位置,模式串T匹配到 j 位置。
如果当前字符匹配成功(即S[i] = T[j]),则i++,j++,继续匹配下一个字符;
如果失配(即S[i] != T[j]),令i = i - (j - 1),j = 0。相当于每次匹配失败时,i 回溯到本次失配起始字符的下一个字符,j 回溯到0。
由于这种匹配方式时间空间耗费所以我们引进kmp及bf算法
什么是kmp?
KMP算法一种改进的模式匹配算法,它的改进在于:每当从某个起始位置开始一趟比较后,在匹配过程中出现失配,不回溯i,而是利用已经得到的部分匹配结果,将一种假想的位置定位“指针”在模式上向右滑动尽可能远的一段距离到某个位置后,继续按规则进行下一次的比较。
规定i是主串S的下标,j是模式T的下标。现在假设现在主串S匹配到 i 位置,模式串T匹配到 j 位置。
如果j = -1,则i++,j++,继续匹配下一个字符;
如果S[i] = T[j],则i++,j++,继续匹配下一个字符;
如果j != -1,且S[i] != P[j],则 i 不变,j = next[j]。这意味着失配时,接下来模式串T要相对于主串S向右移动j - next [j] 位。
该算法最重要的是要理解next及nextval的值的求解过程
源代码如下:
注:该代码最后返回的是下标
#include <stdio.h>
#include <string.h>
typedef struct{
char ch[105];
int length;
}SString;
int Index_BF(SString s, SString t, int pos){
int sum = 0;
int i = pos;
int j = 1;
while(i <= s.length && j <= t.length){
if(s.ch[i -1] == t.ch[j -1]){
i++;
j++;
sum ++;
}else{
sum++;
i = i - j + 2;
j = 1;
}
}
if(j > t.length){
printf("BF j移动了 %d次\n",sum);
return i - t.length;
}else{
printf("BF j移动了 %d次\n",sum);
return -1;
}
}
void get_Next(SString t,int next[]){
int i=1;
next[1]=0;
int j=0;
while (i<t.length) {
if (j == 0||t.ch[i-1]==t.ch[j-1]) {
i++;
j++;
next[i]=j;
}else{
j=next[j];
}
}
return;
}
int Index_KMP(SString s,SString t,int next[]){
int sum = 0;
int i=1;
int j=1;
while ((i <= s.length) && (j <= t.length)){
if (j==0 || (s.ch[i - 1]==t.ch[j - 1])) {
i++;
j++;
sum++;
}
else{
j=next[j];
sum++;
}
}
if (j > t.length) {
printf("KMP j移动 %d次\n",sum);
return (i - t.length);
}
printf("KMP j移动 %d次\n",sum);
return -1;
}
int main() {
SString s;SString t;
// int i= 0;
// int j = 0;
scanf("%s",s.ch);
scanf("%s",t.ch);
s.length = strlen(s.ch);
t.length = strlen(t.ch);
// printf("%d",t.length);
// while((s.ch[i] = getchar())!= '\n'){
// s.length++;
// i++;
// }
// while((t.ch[j] = getchar())!= '\n'){
// t.length++;
// j++;
// }
// s.length--;
// t.length--;
int next[t.length + 5] = {};
get_Next(t,next);
int m=Index_KMP(s,t,next);
int n = Index_BF(s,t,1);
printf("BF %d\n",n);
printf("KMP %d\n",m);
return 0;
}
定义介绍有所参考侵删