文本比較算法三——SUNDAY 算法


 

SUNDAY 算法描述:

字符串查找算法中,最著名的兩個是KMP算法(Knuth-Morris-Pratt)和BM算法(Boyer-Moore)。兩個算法在最壞情況下均具有線性的查找時間。但是在實用上,KMP算法並不比最簡單的c庫函數strstr()快多少,而BM算法則往往比KMP算法快上3-5倍。但是BM算法還不是最快的算法,這里介紹一種比BM算法更快一些的查找算法。

例如我們要在"substring searching algorithm"查找"search",剛開始時,把子串與文本左邊對齊:

substring searching algorithm
search
^

結果在第二個字符處發現不匹配,於是要把子串往后移動。但是該移動多少呢?這就是各種算法各顯神通的地方了,最簡單的做法是移動一個字符位置;KMP是利用已經匹配部分的信息來移動;BM算法是做反向比較,並根據已經匹配的部分來確定移動量。這里要介紹的方法是看緊跟在當前子串之后的那個字符(上圖中的 'i')。

顯然,不管移動多少,這個字符是肯定要參加下一步的比較的,也就是說,如果下一步匹配到了,這個字符必須在子串內。所以,可以移動子串,使子串中的最右邊的這個字符與它對齊。現在子串'search'中並不存在'i',則說明可以直接跳過一大片,從'i'之后的那個字符開始作下一步的比較,如下圖:

substring searching algorithm
     search
     ^

比較的結果,第一個字符就不匹配,再看子串后面的那個字符,是'r',它在子串中出現在倒數第三位,於是把子串向前移動三位,使兩個'r'對齊,如下:

substring searching algorithm
        search
       ^

哈!這次匹配成功了!回顧整個過程,我們只移動了兩次子串就找到了匹配位置,是不是很神啊?!可以證明,用這個算法,每一步的移動量都比BM算法要大,所以肯定比BM算法更快。

下面是這個算法的c代碼。注意我假設了每個字符的值都介於0-127之間(即純ascii碼)。

 

char *qsearch(const char *text, int n, const char *patt, int m)
{
    // get the length of the text and the pattern, if necessary
    if (n < 0)
        n = strlen(text);
    if (m < 0)
        m = strlen(patt);
    if (m == 0)
        return (char*)text;

    // construct delta shift table
    int td[128];
    for (int c = 0; c < 128; c++)
        td[c] = m + 1;

    const char* p;
    for (p=patt; *p; p++)
        td[*p] = m - (p - patt);

    // start searching...
    const char *t, *tx = text;

    // the main searching loop
    while (tx + m <= text + n) {
        for (p = patt, t = tx; *p; ++p, ++t) {
            if (*p != *t)  // found a mismatch
                break;
        }
        if (*p == 0)   // Yes! we found it!
            return (char*)tx;
        tx += td[tx[m]];  // move the pattern by a distance
    }

    return NULL;
}

 

注:這個查找算法稱為Sunday算法,它是BM算法的一種改進型。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM