(一)BF(Brute Force)——求子串位置的定位函数(普通的模式匹配算法)
int Index(char S[],char T[],int pos){
//返回子串T在主串S中第pos个字符之后的位置,若不存在,则函数值为0
//其中,T非空,1<=pos<=StrLength(S)
int i=pos,j=1;
while(i<=S[0]&&j<=T[0]){
if(S[i]==T[j]){ //继续比较后继字符
++i;
++j;
}
else{ //指针后退,重新开始分配
i=i-j+2; //!!!下有附图
j=1;
}
}
if(j>T[0])return i-T[0];
else
return 0;
}
注意:
(1)字符数组的第一个元素存储元素个数length
(2)一般匹配字符串时,我们从目标字符串str(假设长度为n)的第一个下标选取和ptr长度(长度为m)一样的子字符串进行比较,如果一样,就返回开始处的下标值,不一样,选取str下一个下标,同样选取长度为n的字符串进行比较,直到str的末尾(实际比较时,下标移动到n-m)。这样的时间复杂度是O(n*m)。
(3)此算法的最低时间复杂度为 O(n+m),有时这种匹配的效率十分低下,例如:当模式串为‘00000001’时,主串为‘00000000000000000000000000000000000000000000000000001’,由于模式中前7个字符均
为“0”,又因为主串中前52个字符均为“0”,每趟比较模式都在最后一个字符出现不等,此时需将指针i回溯到 i-6 的位置上,并从模式的第一个字符开始重新比较,整个匹配过程中指针 i 需要回溯45次 , 则while循环次数为 46*8*(index*m),可见算法在最坏情况下时间复杂度为O(n*m),这和计算机的存储情况很类似,因为在计算机中,一切数据信息都是以二进制的形式存储的。
(3)匹配过程中的指针回退较难理解,附图如下:
附上完整测试代码:
#include<iostream>
#include<cstdio>
#define maxn 100
int Index(char S[],char T[],int pos){
//返回子串T在主串S中第pos个字符之后的位置,若不存在,则函数值为0
//其中,T非空,1<=pos<=StrLength(S)
int i=pos,j=1;
while(i<=S[0]&&j<=T[0]){
if(S[i]==T[j]){ //继续比较后继字符
++i;
++j;
}
else{ //指针后退,重新开始分配
i=i-j+2;
j=1;
}
}
if(j>T[0])return i-T[0];
else
return 0;
}
print(char s[]){
for(int i=1;i<=s[0];i++)
printf("%c",s[i]);
printf("\n");
}
int main(){
char s1[maxn],s2[maxn];
int res,pos;
scanf("%d",&s1[0]);
for(int i=1;i<=s1[0];i++)
scanf("%c",&s1[i]);
print(s1);
scanf("%d",&s2[0]);
for(int i=1;i<=s2[0];i++)
scanf("%c",&s2[i]);
print(s2);
res=Index(s1,s2,pos);
printf("%d\n",res);
return 0;
}
如果对字符串的存储实现和基本操作还不太了解的,欢迎戳 字符串(一)——字符串的存储实现与基本操作