数据结构和算法 <字符串>(六、字符串匹配 (BF暴力解法))

152 阅读3分钟

终于来到了子字符串匹配,这个知识点很重要,也是经常用到的。虽然我们平时都是调用API中的函数,比如indexOf(),find()等字符串处理函数,但是我们也要学学底层的字符串匹配算法。

6.1 介绍

BF算法中的BF是Brute Force的缩写,中文叫做暴力匹配算法,也叫朴素匹配算法。

这种算法是我们刚开始想的那种字符串匹配的思想。当然它也确实是简单,好懂,但是也有缺点就是性能不高。

在开始讲解之前,我们先了解一下两个概念,我之前一直没搞懂这两个概念,所以就很懵逼。

我们在字符串A中查找字符串B,那字符串A就是主串,字符串B就是模式串。主串的长度一般都是大于模式串。(我也不知道为什么叫模式串,确实有点懵逼)

6.2 解析BF算法

BF算法中也是利用了我们人的正常思想(大佬跳过)去匹配字符串,就是我把模式串去匹配主串,如果不匹配,就移到第二位,再次匹配主串,然后一直这样循环。

在这里插入图片描述

看这图应该都能明白了,比较常见的一种匹配思想。

6.3 代码

之前没有正式写过这种字符串匹配算法,不难,就当一次练习,不写代码总感觉不完整。

int BF::search(std::string pat, std::string txt)
{
    // 暴力算法就是两层遍历
    int N = pat.length();
    int M = txt.length();
    for(int i = 0; i <= N-M; i++) 
    {
        int j;
        for(j = 0; j < M; j++)
        {
            if(pat.at(i) != txt.at(j))
            {
                break;
            }
        }
        if(j == M) return i;    // 知道匹配的
    }
    return 0;   // 未找到匹配
}

比较简单,从上面代码中看,在极端的情况下,如果主串是"aaa...aaaa"很多个a,模式串是"aaaab",这样是不是很坑爹,我们每次都要比较m个字符,然后要对比n-m+1次,所以这个算法最坏的复杂度为O(n*m)。

6.4 总结

尽管理论上,BF算法的时间复杂度很高,是O(n*m),但在实际开发中,它确实一个比较常用的字符串匹配算法,为什么呢?

  1. 实际开发中,大部分情况下,模式串和主串的长度都不会太长,而且每次模式串与主串中子串匹配的时候,中途遇到不能匹配的字符的时候,就可以停止了。不需要把m个字符都对比一下。统计意义上,大部分情况下,算法执行效率要比这个高很多。
  2. 朴素字符串匹配算法思想简单,代码实现也非常简单,简单意味着不容易出错,如果有bug也容易暴露和修复。在工程中,在满足性能要求的前提下,简单是首选。

这一篇是有点短,不过为了过渡到正式进入字符串匹配还是有点意义的,下一篇的RK算法也不会很难。