BF
就是暴力求解,比较常见的算法,就是将模式串与主串进行比较,从第一位开始比较,若当前字符相同时,继续比较下一个字符,直到比完模式串。若字符不同,则开始从主串的第二位、模式串的第一位开始重新比较,依次类推。
例题
class Solution {
public:
int strStr(string haystack, string needle) {
int hlen=haystack.length();
int nlen=needle.length();
//特殊情况
if(hlen<nlen) return -1;
if(nlen==0) return 0;
int i,j;
for(i=0;i<hlen-nlen+1;i++)
{
for(j=0;j<nlen;j++)
if(haystack[i+j]!=needle[j])
break;
if(j==nlen)
return i;
}
return -1;
}
};
BM
BF简单易懂,但每次遇到不匹配的字符时,又需要后移后重新比较,费时费力,但BM可以使你跳过某些步骤。有必要说的是BM算法是从模式串的右侧到左侧的顺序进行比较。
下面介绍几种规则:
坏字符规则
当我们比较时发现的第一个不匹配的字符,我们将主串的这个字符称为坏字符。如下图:
当我们发现坏字符后,检查模式串是否也有该字符。分为以下几种情况。
1、若没发现含有该字符,将模式串移到坏字符的下一位。如下图:
2、若模式串包含该坏字符,则移动模式串,直到该字符与主串坏字符对齐为止。然后开始下一轮比较。如下图:
3、若模式串不仅含有该坏字符,还拥有多个的话,我们以最靠右的、与坏字符相同的字符 与 坏字符对齐即可。如下图:
但如果遇到下面这种情况呢?
坏字符是b,根据上述要求3,要将模式串最右边的b移至与坏字符最齐处,这种情况肯定是不行的,不往右移动,甚至往左移,那么我们怎么解决这种无法移动的情况呢?
若使用按照坏字符规则进行移动不合理时,我们可以根据好后缀规则。
好后缀规则
1、我们从右往左比较,发现cac已经匹配成功,然后发现坏字符c,此时已经匹配好的cac就成为了好后缀,我们在模式串查找,如果找到了另一个和好后缀相匹配的串,移动至对齐。如下图:
2、如果在模式串的头部没有发现好后缀,发现好后缀的子串也是可以的,还是移动至对齐。一定要在头部!如下,很显然
总结:
- 当模式串含有一个或多个好后缀时,无论是在串的头部还是中间,都可以按照规则进行移动(多个好后缀时,以最右侧的好后缀为准)。
- 当有好后缀的子串时,也可以按照规则移动,但是子串只能在开头,中间部分含有好后缀的子串时不可以的。
- 当模式串尾部出现不匹配的情况,也就是说没有好后缀,不满足上述条件只能根据坏字符规则就行移动。
KMP
KMP与BM本质上一样,都是找字符串中的相同部分,KMP找到是最长公共前后缀。
此时,最长公共前后缀为
“
a
b
a
”
“aba”
“aba”。对齐如下图:
KMP原理就是这样。原理很简单,关键在于如何利用指针的移动和位置的寻找,达到像图片中对齐的效果。