字符串的定位运算通常称为串的模式匹配或者串匹配。此运算的运用非常广泛,比如搜索引擎、拼写检语句翻数据压缩等应用中,都需要进行串匹配。
最简单也是最暴力的方法就是BF(Brute-Force)算法
BF算法
模式匹配并不是从主串的第一个位置开始,可以指定主串中查找的起始位置 pos。如果采用字符串顺序存储结构。可以不依赖其他串操作的匹配算法。
算法步骤:
- 先定义两个指针和j,分别指向主串S和字串T需要比较的字符位置,i的初值是pos,j的初值是1;
- 如果两个串都没比较到串尾,即i和j都分别小于S和T的长度时候,循环执行下面的操作:
①S.ch[i]和T.ch[j]比较,若相等,则i和j分别指向下一个位置,继续比较后续字符;
②若不相等,指针后退重新开始比较,从主串的下一个字符(i=i-j+2)起再重新和模式的第一个字符(j=1)比较。
3.如果j>=T.length,说明模式T中的每个字符依次和主串S中的连续字符串序列相等,则匹配成功。返回和模式T中第一个字符相等字符在朱传S中的序号(i-T.length);否则匹配不成功返回0。
算法描述:
#include <stdio.h>
#include <string.h>
int BF(const char *s, const char* sub, int pos)//O(n*m)
{
int i = pos;
int j = 0;
int lens = strlen(s);
int lensub = strlen(sub);
while (i<lens && j<lensub)
{
if (s[i] == sub[j])
{
i++; //若相同,两个指针分别向后移动一个位置。
j++;
}
else
{
i = i - j + 1;//i退回到当前匹配失败初始的下一个
j = 0;//j回退到0
}
}
if (j >= lensub)
{
return i - j;
}
else
{
return -1;
}
}
int main()
{
char *s = "ababcabcdfabcde";
char *sub = "abcd";
printf("%d\n", BF(s, sub, 0));
return 0;
}
算法分析:
时间复杂度分析:
就这个是加班复杂度的分析,反正教材上严奶奶的分析我是看的一头雾水啊!
最好情况:
最好情况简单来说就是,假如我在主串的第i个位置及以后都匹配成功了,那么在此之前模式串的第一个字符只要和主串比较就失败,所以说第i个位置之前就一共比较了
i
−
1
i-1
i−1次,然后我们再加上后面匹配成功的模式串需要匹配的次数(模式串长度
m
m
m),总的就一共匹配了
i
−
1
+
m
i-1+m
i−1+m次。
对于匹配成功的串来说:
在主串的位置就是
n
−
m
+
1
n-m+1
n−m+1,假设这
n
−
m
+
1
n-m+1
n−m+1位置上匹配次数相等,那么
所以最好情况下平均时间复杂度是O(n+m)。
最坏情况:
那么话又说回来,要是我在主串的第i个位置匹配成功了,但是之前的i-1个位置上的匹配的时候,偏偏就是匹配到模式串的最后一个字符 他才告诉我你匹配失败了(这不就是搞我心态嘛)!那么仔细想来,和上面的最好情况相比较,每个位置就必须匹配m次,所以说第i个位置之前就一共匹配了
(
i
−
1
)
∗
m
(i-1)*m
(i−1)∗m次,那么这种情况的比较次数就是
(
i
−
1
)
∗
m
+
m
=
i
∗
m
(i-1)*m+m=i*m
(i−1)∗m+m=i∗m次。
对于匹配成功的串来说:
在主串的位置就是
n
−
m
+
1
n-m+1
n−m+1,假设这
n
−
m
+
1
n-m+1
n−m+1位置上的匹配次数相同,那么:
所以最坏情况下平均时间复杂度是O(n*m)。