字符串匹配
1.BF
Brute Force的缩写,也叫做暴力匹配算法,或者朴素匹配算法。
主串和模拟串
假设从A串(长度为n)中查找B串(长度为m),所以n>m
- A就是主串,
- B就是模拟串
朴素匹配算法的核心思想就是:在主串中,检查起始位置分别为0、1、2…n-m且长度为m的n-m+1个字串,看有没有和模拟串匹配的。
最坏情况的时间复杂度为O(n*m)
但是实际开发中确实一个比较常用的字符串匹配算法:
- 实际软件开发中,大部分情况下,模拟串和主串的长度都不会太长。而且匹配的时候中途遇到不能匹配的字符就直接停止了,并不是把所有的字符都比较一次。所以统计意义上,大部分情况下,算法执行效率比最坏时间复杂度要高的多。
- 思想简单,胆码的实现也比较简单。简单意味着不容易出错,出现bug也容易修复,在满足工程的需求下,简单事首先。Kiss it Simple and Stupid KISS设计原则
2.RK
Rabin-Karp BF算法的升级版本。
因为BF算法子串和主串中比较的时候,是一个字符一个字符进行对比的所以效率比较低。RK算法对他进行了升级,对n-m+1个字串分别进行求hash值,然后和子串的hash值做比较。然后根据特定的情况去制定特定的hash算法,还需要考虑到散列冲突的情况怎么处理等等。效率事要比BF高,但是也是存在时间复杂度退化的问题,最主要的就是hash算法的设计以及散列冲突的解决。
hash算法的设计技巧
3.BM算法
BM算法的核心思想:其实非常简单,BF和RK都是匹配字符串的时候都是一位一位向后边移动的,BM算法其实就是在找大到一些规律可以跳过一些肯定不会匹配的情况,也就是说一次向后边移动很多位。
BM算法包含两种情况:
- 坏字符原则
- 好后缀原则
不管是坏字符原则还是好后缀原则其实都是求没有匹配到字符串情况下最佳的后移步数。
坏字符原则(bad character rule)
坏字符原则,从后向前比较主串和模拟串的字符值,知道出现第一个不相等的值为止,记录下主串对应的字符值即为坏字符,对应在模拟串的索引为j,然后再模拟串中继续寻找等于坏字符的索引值记为i,要移动的步数step=j-i(当模拟串没有找到坏字符的时候i=-1)。如果坏字符在模拟串中出现多次,为了保证移动步数的正确性,选取最后一次出现的索引为准。
翻译成代码如下:
1.首先是一个散列算法
把模拟串散列在数组bc中,值就是对应模拟串的索引数,查找的时候通过坏字符的asicc值进行查找,不等于-1,说明模拟串中存在坏字符。
/**
*
* @param b 模拟串
* @param bc 模拟串对应的散列表
* @param m 模拟串的长度
*/
private static void generateBC(char[] b,int[] bc,int m){
//1.初始化散列表
for (int i = 0; i < SIZE; i++) {
bc[i]=-1;
}
//2.将模拟串散列在数组bc中,值就是对应模拟串的索引数
for (int i = 0; i < m; i++) {
int ascii = (int) b[i];
bc[ascii]=i;
}
}
2.第二步就是坏字符原则的算法代码了:(注释就直接写在代码里了)
/**
* 仅仅只考虑坏字符规则
* 其实算法很简单 就是 比较从后向前与主串进行比较 ,找出坏字符串的位置 然后计算 查找的后移数 重新进行查找,但是这种
* 查找存在隐患会出现 后移位数为负的情况 这就需要好后缀规则了。
* @param a 主串
* @param n 主串长度
*