终于来到了子字符串匹配,这个知识点很重要,也是经常用到的。虽然我们平时都是调用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),但在实际开发中,它确实一个比较常用的字符串匹配算法,为什么呢?
- 实际开发中,大部分情况下,模式串和主串的长度都不会太长,而且每次模式串与主串中子串匹配的时候,中途遇到不能匹配的字符的时候,就可以停止了。不需要把m个字符都对比一下。统计意义上,大部分情况下,算法执行效率要比这个高很多。
- 朴素字符串匹配算法思想简单,代码实现也非常简单,简单意味着不容易出错,如果有bug也容易暴露和修复。在工程中,在满足性能要求的前提下,简单是首选。
这一篇是有点短,不过为了过渡到正式进入字符串匹配还是有点意义的,下一篇的RK算法也不会很难。