Sunday算法解決字符串匹配問題

概述

提起字符串匹配可能更多人會想到KMP算法,該算法時間複雜度爲O(m+n),而且也是我們在學習數據結構過程中最早接觸到的比較好的算法。但KMP算法需要在模式字符串有關聯的情況下,也即模式字符串前後綴字符相似度較高的情況下匹配效率比較高。但是在實際應用場景中模式字符串更多情況下是無規律的,因此在工程應用中字符串匹配問題的解決更多的使用的是sunday算法。

解題思路

sunday算法較之於BM算法最大的不同點在於sunday算法在匹配的過程中主串中參加匹配的最末位字符的下一位字符。

  • 如果末尾的下一位字符(如該字符爲'a')沒有在模式字符串中出現過,則直接跳到'a'的下一位字符開始新一輪的比較
  • 如果模式字符串中包含'a',則將模式字符串中從左到右中最早出現的字符'a'與源字符串中的'a'對應開始新一輪的匹配

我們下邊舉一個例子來說明sunday算法的匹配過程。比如在一個主串"substring searching"中查找模式串"search"。

  1. 開始時,將模式字符串和主字符串左側對齊開始進行匹配

img

  1. 在匹配的過程中發現在第二個字符e處出現匹配失敗的情況。此時我們關注參與匹配的最末尾字符的下一位即i,由於模式字符串中並沒有i,因此模式字符串直接跳過一大片,向右移動位數=模式字符串長度+1,也即移動到字符n的位置。

  1. 在新一輪的匹配過程中發現第一個字符便出現了不匹配的情況。然後我們看到參與匹配的末尾字符的下一位字符爲r,並且r存在於模式字符串中因此可以將模式字符串移動3位(移動到模式字符串中的r和主字符串中的r對齊)如下:

img

  1. 在新一輪匹配過程中發現匹配成功,結束匹配返回匹配的位置。

代碼

class Solution {
    //使用sunday算法來求解
    public int strStr(String haystack, String needle) {
        //邊界判斷
        if(needle.equals("")||needle==null){
            return 0;
        }
        if(haystack==null){
            return -1;
        }
        char [] haystackArray=haystack.toCharArray();
        char []needleArray=needle.toCharArray();
        int haystackLength=haystackArray.length;
        int needleLength=needleArray.length;
        //定義偏移數組
        int move[]=new int[256];
        //對偏移數組進行初始化工作
        for(int i=0;i<256;i++){
            move[i]=needleLength+1;
        }
        for(int i=0;i<needleLength;i++){
            move[needleArray[i]]=needleLength-i;
        }
        //模式字符串第一個字符在匹配過程與源字符串對應的未知,j表示當前已經匹配的字符個數
        int s=0,j=0;
        //進行匹配
        while(s<=haystackLength-needleLength){
            j=0;
            while(haystackArray[s+j]==needleArray[j]){
                j++;
                if(j==needleLength){
                    return s;
                }
            }
            if(s<haystackLength-needleLength){
                s+=move[haystackArray[s+needleLength]];
            }else{
                return -1;
            }
        }
        return -1;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章