字符串匹配算法

字符串匹配算法

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、如果在模式串的头部没有发现好后缀,发现好后缀的子串也是可以的,还是移动至对齐。一定要在头部!如下,很显然
在这里插入图片描述
总结:

  1. 当模式串含有一个或多个好后缀时,无论是在串的头部还是中间,都可以按照规则进行移动(多个好后缀时,以最右侧的好后缀为准)。
  2. 当有好后缀的子串时,也可以按照规则移动,但是子串只能在开头,中间部分含有好后缀的子串时不可以的。
  3. 当模式串尾部出现不匹配的情况,也就是说没有好后缀,不满足上述条件只能根据坏字符规则就行移动。

KMP

KMP与BM本质上一样,都是找字符串中的相同部分,KMP找到是最长公共前后缀
在这里插入图片描述
此时,最长公共前后缀为 “ a b a ” “aba” aba。对齐如下图:
在这里插入图片描述
KMP原理就是这样。原理很简单,关键在于如何利用指针的移动和位置的寻找,达到像图片中对齐的效果。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值