字符串匹配一直是计算机领域热门的研究问题之一,多种算法层出不穷。字符串匹配算法有着很强的实用价值,应用于信息搜索,拼写检查,生物信息学等多个领域。
今天介绍几种比较有名的算法:
1. BF
2. BM
3. Sunday
4. KMP
—,BF算法
BF(Brute Force)算法又称为暴力匹配算法,是普通模式匹配算法。
其算法思想很简单,从主串S的第pos个字符开始,和模式串T的第一个字符进行比较,若相等,则主串和模式串都后移一个字符继续比较;若不相同,则回溯到主串S的第pos+1个字符重新开始比较。
依次类推,直到模式串T中每个字符依次和主串S中的一个连续字符串全部相等时,则匹配成功,返回模式串T的第一个字符在主串S中的位置;若主串遍历完也没有成功,则匹配失败。
算法步骤如下:
下标i 0 1 2 3 4 5 6 7 8 9
主串S a b a b c a b c a c
模式串T a b c a
第一次比较,从左到右,S[0] = T[0],计数器++;比较S[1] = T[1],i++;当s[2] != T[2],主串回溯,从S[1]重新开始比较。
下标i 0 1 2 3 4 5 6 7 8 9
主串S a b a b b a b c a c
模式串T a b c a
也就是说,主串i从0开始,每次比较失败i++,重新比较,直到
下标i 0 1 2 3 4 5 6 7 8 9
主串S a b a b b a b c a c
模式串T a b c a
i = 5,匹配成功。返回 i=5。
可推得,BF算法在最坏情况下需要比较,主串长度M 乘以 模式串长度N, 为-O(M * N)。
代码实现如下:
int BF(const char *str1, const char *str2)
{
int str1_len = strlen(str1);
int str2_len = strlen(str2);
int i = 0;
int j = 0;
if(str1 == NULL || str2 == NULL){
return -1;
}
while(i < str1_len && j < str2_len){
if(str1[i] == str2[j]){
i++;
j++;
//相等则继续逐个比较
}
else{
i = i -j + 1;
j = 0;
//不相等则主串回溯,重新比较
}
}
if (j == str2_len){
return i - j;
}else{
return -1;
}
}
BF算法简单易懂,但是这个算法效率很差,原因在于每次失败后回溯,浪费了之前的比较,导致了很多次的无用比较,时间损耗较大。
二,BM算法
BM(Boyer Moore)算法是1977年,Robert S.Boyer和J Strother Moore提出了一种在O(n)时间复杂度的匹配算法。时间复杂度要低于BF。
BM算法之所以能够在模式匹配中有更高的的效率,主要是因为BM算法构造了两个跳转表,分别叫做 坏后缀表 ,和 好后缀表 。这两个表涉及了BM算法中的两个规则:
坏字符规则:当文本串中的某个字符跟模式串的某个字符不匹配时,我们称文本串中的这个失配字符为坏字符,此时模式串需要向右移动,移动的位数 = 坏字符在模式串中的位置 - 坏字符在模式串中最右出现的位置。此外,如果”坏字符”不包含在模式串之中,则最右出现位置为-1。
好后缀规则:当字符失配时,后移位数 = 好后缀在模式串中的位置 - 好后缀在模式串上一次出现的位置,且如果好后缀在模式串中没有再次出现,则为-1。
算法步骤如下:
1. 首先,”文本串”与”模式串”头部对齐,从尾部开始比较。”S”与”E”不匹配。这时,”S”就被称为”坏字符”(bad character)