一種基於Sunday演算法的單模式字串匹配演算法

2021-06-27 13:51:38 字數 4737 閱讀 3201

最近看了幾個字串匹配演算法,偶然想到對sunday演算法的一種可能的改進(改變)

單模式字串匹配

sundy演算法四目前最快的字串匹配演算法,本文在sunday基礎上做了一些改進(或者改變),能在一定程度上提高sunday演算法的執行效率,較有限,但也算是一種思路。

sunday演算法:

從前往後匹配,每次匹配不成功,關注的是尾部的後一字元(設該字元為x)是否在模式串中出現。若出現,移動模式串,使x與模式串中最後一次出現的該字元(下標最大)對齊;若沒出現過,移動模式串使其頭字元與x的下一字元對齊。總體思想是盡可能大步長地往後移動模式串。

總體思想依然是盡可能大步長後移模式串。sundayevening演算法每次從後往前匹配,每次匹配不成功,不只關注尾部後一字元(設為x),也關注當前匹配不成功的字元(設為y)。因為:當尾x在模式串中,而y不在模式傳中時,sunday演算法可能沒有找到最大移動步長。

sundayevening的做法是,每當y匹配不成功,若y在模式串中則計算移動模式串使其相應字元與y對齊時的步長,若y不在字串中,計算移動模式串使其頭部與y後一字元對齊時的步長,總之,可以計算出按y來移動模式串的步長。再來看x,當x不在字串中時,操作與sunday演算法一致,若x在字串中,計算按x移動的步長,與上述按y移動的步長比較,取較大的來進行移動。這樣就盡可能的獲得了較大的移動步長。而sundayevening從後往前匹配顯然也有助於獲得更大步長(y靠後的概率大)。

sunday和sundayevening的比較:

sundayevening演算法通過兩種措施①從後向前匹配②比較步長選較大者,提高了獲得最大步長的可能性。但是會增加一些比較操作。當模式串長度極大或極小時,效率與sunday基本無差別,但是在中間某一區域內,sundayevening演算法可以獲得約百分10到百分之15的效率提公升。(測試資料為隨機字串,字元範圍為ascii碼中96個可列印字元)。

**中寫了三個演算法:sunday、kmp、sundayevening(為了比較,將kmp一同寫出)

測試資料:隨機字串(字元範圍為96個可列印字元)

測試串長度:1000000000

模式串長度:10

測試結果與模式串長度、文字串長度、字元範圍均有關係,文字串較小或模式串較大時效率與sunday演算法基本無差(但貌似不會低於sunday)。

一次測試的結果:效率提公升百分之14

具體**:

#pragma once

#include#include#include#includeusing namespace std;

#define random(x) (rand()%x)

//*********************kmp演算法:***********************

void getnext(const unsigned char shortlist, int next, int shortlength)

else

//從未加shortlist[index]之前的子串的字首中,尋找更小的字首(字首的字首),該字首與字尾的字尾相同,然後看能不能匹配

pointer = next[pointer]; }}

int kmp(const unsigned char longlist, const unsigned char shortlist, int next, long longlength, int shortlength)

else//取前面與 #lp之前子串的某字尾# 相同的某字首後的第乙個元素

}if (sp == shortlength)

return(lp - shortlength);

else

return -1;}/

///*********************suday演算法:***********************

void getmaxindex(int maxindex, const unsigned char* shortlist, const int shortlength)

}int sunday(const unsigned char shortlist, const unsigned char longlist, int maxindex, const int shortlength, const long longlength)

else if (lrear + 1 >= longlength)//檢查到末尾了,跳出迴圈

break;

else if (maxindex[longlist[lrear + 1]] == -1)//後一字元不在shortlist中

else//後一字串在shortlist中

}return result;}/

//***********************sunday改進演算法*************************

int sundayevening(const unsigned char shortlist, const unsigned char longlist, int maxindex, const int shortlength, const long longlength)

else if (lrear + 1 >= longlength)//檢查到末尾了,跳出迴圈

break;

else if (maxindex[longlist[lrear + 1]] == -1)//後一字元不在shortlist中

else

else

}} return result;

}void main()

for (long i = 0; i < longlength - shortlength; i++)

for (long i = 0; i < shortlength; i++)

longlist[i + longlength - shortlength] = shortlist[i];

dword start_time = gettickcount();

int maxindex[256];//存shortlist中出現有的字元在shortlist中最後一次出現的位置,同時也標記那些字元出現在了shortlist中

getmaxindex(maxindex, shortlist, shortlength);

int sunday_result = sunday(shortlist, longlist, maxindex, shortlength, longlength);

dword sunday_end_time = gettickcount();

if (sunday_result < 0)

cout << "未在文字串中找到模式串!" << endl;

else

cout << "模式串在文字串中的起始下標為:" << sunday_result << endl;

cout << "the sunday run time is:" << (sunday_end_time - start_time) << "ms!" << endl;//輸出執行時間

int *next = new int[shortlength];

//next[index]存index前面子串中字首後的第乙個元素位置,不匹配時換這個位置的元素看是否匹配

//next是對應子串最長字首長度陣列的右移(左端補-1)

getnext(shortlist, next, shortlength);

int kmp_result = kmp(longlist, shortlist, next, longlength, shortlength);

if (kmp_result < 0)

cout << "未在文字串中找到模式串!" << endl;

else

cout << "模式串在文字串中的起始下標為:" << kmp_result << endl;

dword kmp_end_time = gettickcount();

cout << "the kmp run time is:" << (kmp_end_time - sunday_end_time) << "ms!" << endl;//輸出執行時間

getmaxindex(maxindex, shortlist, shortlength);

int sunday2_result = sundayevening(shortlist, longlist, maxindex, shortlength, longlength);

dword sunday2_end_time = gettickcount();

if (sunday2_result < 0)

cout << "未在文字串中找到模式串!" << endl;

else

cout << "模式串在文字串中的起始下標為:" << sunday2_result << endl;

cout << "the sundayevening run time is:" << (sunday2_end_time - kmp_end_time) << "ms!" << endl;//輸出執行時間

cout << "提高了:" << 1 - (double)(sunday2_end_time - kmp_end_time) / (sunday_end_time - start_time) << endl;

system("pause");

}

一種基於SJF和PSA演算法的折中演算法

一 短作業優先演算法 sjf 的缺點 1 必須預知作業的執行時間 2 對長時間非常不利,會出現飢餓現象 3 人 機無法實現互動 4 不能保證緊迫性作業得到及時處理 二 基於sjf演算法和psa演算法的折中演算法 1 為每個作業設定乙個相同的最長等待時間t,同時由外部賦予每個作業相應的優先順序 2 在...

一種基於密度峰值的聚類演算法

2014年science刊發了一篇標題為clustering by fast search and find of density peaks的文章,文章中介紹了一種基於密度峰值的聚類演算法。傳統的聚類演算法k means,通常不適用於非球形的簇。這裡所謂的球形簇是根據k means演算法基本原理得...

一種基於ASEF演算法的高速特徵點定位演算法

鏈結2 演算法相關部落格1 總結 以定位人眼為例,我們的目的是讓影象 f f 通過乙個相關濾波器 h role presentation h h,然後就能得到人眼響應圖 g g f h g這 裡以小寫 為空間域 大寫為 頻域,代表卷積 role presentation f h g這裡 以小寫為 空...