字符串查找算法

字符串查找

字符串的一种基本操作就是字符串查找:给定一段长度为N的文本和一个长度为M的模式字符串,在文本中找到一个和该模式相符的子字符串。

一、暴力子字符串查找算法(Brute Force Algorithm)

public static int search(String pat,String txt){
    int M = pat.length();
    int N = txt.length();
    
    for(int i = 0;i <= M-N;i++){
        int j;
        for(j = 0;j < M; j++){
            if(txt.charAt(i+j) != pat.charAt(j))
                break;
        }
        if(j === M) return i;	//找到匹配
       
    }
    return N;	//未找到匹配
}

该算法的基本思路就是将字符一个一个地进行比较:

  • 如果pattxt两个字符串的第一个字符相同就比较第二个字符,如果相同就一直继续;
  • 如果其中有某一个字符不同,则将pat字符串向后移一位,将txt字符串的第二个字符与pat的字符串的第一个字符重新开始比较。
  • 循环往复,一直到结束。
txt[] = “AAAAAAAAAAAAAAAAAB”
pat[] = “AAAAB”

如果是朴素算法一个一个对比的话,pat[]一个一个地右移。
字符串查找算法_第1张图片
字符串查找算法_第2张图片

可以发现暴力算法称不上高效,而这些特点就是原因。

  1. 没有预处理阶段;
  2. 滑动窗口总是后移 1 位;
  3. 对模式中的字符的比较顺序不限定,可以从前到后,也可以从后到前;
  4. 匹配阶段需要 O((n - m + 1)m) 的时间复杂度;
  5. 需要 2n 次的字符比较;

二、Knuth-Morris-Pratt子字符串查找算法

KMP算法伪代码:

while(i < S.length){
	if(S[i] == T[j]){//如果相同,两个下标同时往后延
		i++;
		j++;
		if(j == T.length){
			//输出匹配到的字符串下标为:j - i
			break;
		}	
	}else{//如果不相等,移动相应位置
		if(j == 0){//如果模式串(T)下标为0,证明一开始都没有匹配成功
			i++; //目标串(S)下标往后移动一位,模式串(T)不变
		}else{//如果模式串(T)下标不是0
			j = D[j - 1]; // j从D数组的j-1开始匹配,i不变
		}
	}
}

三、Boyer-Moore字符串查找算法

它的效率比KMP算法更为高效(3~5倍)

BM算法的特点:

  1. 将模式串和目标串(要进行查找的串)左端对齐,从右向左比较
  2. 应用到了两种启发式规则,即坏字符规则好后缀规则 ,来决定向右跳跃的距离。
  3. 在BM算法匹配的过程中,取坏字符规则和好后缀规则中跳跃的较大者作为跳跃的距离

BM算法的比较基本流程:

设文本串T = abcecabe
模式串为P = abcab
首先将T与P进行左对齐,然后进行从右向左比较 ,如下图所示:

字符串查找算法_第3张图片

图中,第一个不匹配的字符(红色部分)为坏字符,已匹配部分(绿色)为好后缀

四、Rabin-Karp指纹字符串查找算法

你可能感兴趣的:(算法,算法,网络,数据库)