字符串匹配 sunday算法

原題:lintcode題目

字符串查找(又稱查找子字符串),是字符串操作中一個很有用的函數。你的任務是實現這個函數。

對於一個給定的 source 字符串和一個 target 字符串,你應該在 source 字符串中找出 target 字符串出現的第一個位置(從0開始)。

如果不存在,則返回 -1


字符串匹配最常見的就是kmp算法,不過kmp算法對於我來說過於的複雜,我在網上查找,發現了更爲簡單,易於理解的sunday算法

Sunday算法是Daniel M.Sunday於1990年提出的字符串模式匹配。其核心思想是:在匹配過程中,模式串發現不匹配時,算法能跳過儘可能多的字符以進行下一步的匹配,從而提高了匹配效率。


unday是一個字符串模式匹配算法。算法的概念如下:
Sunday算法是Daniel M.Sunday於1990年提出的一種字符串模式匹配算法算法。其核心思想是:在匹配過程中,模式串並不被要求一定要按從左向右進行比較還是從右向左進行比較,它在發現不匹配時,算法能跳過儘可能多的字符以進行下一步的匹配,從而提高了匹配效率。
假設在發生不匹配時S[i]≠T[j],1≤i≤N,1≤j≤M。此時已經匹配的部分爲u,並假設字符串u的長度爲L。如圖1。明顯的,S[L+i+1]肯定要參加下一輪的匹配,並且T[M]至少要移動到這個位置(即模式串T至少向右移動一個字符的位置)。
1 Sunday算法不匹配的情況
分如下兩種情況:
(1) S[L+i+1]在模式串T中沒有出現。這個時候模式串T[0]移動到S[L+i+1]之後的字符的位置。如圖2。
2 Sunday算法移動的第1種情況
(2)S[L+i+1]在模式串中出現。這裏S[L+i+1]從模式串T的右側,即按T[M-1]、T[M-2]、…T[0]的次序查找。如果發現S[L+i+1]和T中的某個字符相同,則記下這個位置,記爲k,1≤k≤M,且T[k]=S[L+i+1]。此時,應該把模式串T向右移動M-k個字符的位置,即移動到T[k]和S[L+i+1]對齊的位置。如圖3。
3 Sunday算法移動的第2種情況
依次類推,如果完全匹配了,則匹配成功;否則,再進行下一輪的移動,直到主串S的最右端結束。該算法最壞情況下的時間複雜度爲O(N*M)。對於短模式串的匹配問題,該算法執行速度較快。
Sunday算法思想跟BM算法很相似,在匹配失敗時關注的是文本串中參加匹配的最末位字符的下一位字符。如果該字符沒有在匹配串中出現則直接跳過,即移動步長= 匹配串長度+1;否則,同BM算法一樣其移動步長=匹配串中最右端的該字符到末尾的距離+1。
在這裏給出代碼.


int strStr(const char *source, const char *target) {
      if(source == NULL || target == NULL)
            return -1;
    
     int i,j,pos=0;
    int len_s,len_d;
    int next[256]={0};//next數組保存在target中出現字符順序,這樣在匹配的時候不需要重新查找,

    len_d=strlen(target);
    for(j=0;j<256;++j)                       //初始化next數組,如果next沒有在target中出現,next爲target長度+1,即跳過整個target長度
        next[j]=len_d + 1;
    for(j=0;j<len_d;++j)                        //設置next數組
        next[target[j]-'0']=j+1; <span style="white-space:pre">		</span>//next的字符在target出現,者next值爲target內的順序+1
    while( pos<(len_s-len_d+1) )               //遍歷原串          
    {
        i=pos;
        for(j=0;j<len_d;++j,++i)              //比較
        {
            if(source[i]!=target[j])                //一旦不匹配,原串就按照next跳轉
            {
                pos+=next[source[pos+1]-'0'];//如果下一個字符在target出現,則跳過next的值,否則跳過這個target長度
                break;
            }
        }
        if(j==len_d)
            return pos;
    }
    return -1;                  
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章