幾個字串匹配演算法

2021-06-17 20:29:39 字數 2987 閱讀 1684

下面依次來說說樸素演算法,rabin-karp演算法,knuth-morris-pratt演算法,boyer-moore演算法,sunday演算法,以及aho-corasick等演算法。

樸素演算法是一種非常簡單的演算法,時間複雜度是o(nm)(n為文字串長度,m為模式串長度,下同),不需要預處理。

int *****_matcher(const char * txt, const char * pat,

int offset)

return c;

}

從**中可以看出,它暴力地依次比較,演算法簡單但時間複雜度太高,不適合在資料量大或注重效率的情況下使用。

rabin-karp演算法

樸素演算法之所以複雜度達到o(nm),是因為它比較的過程沒有優化,沒有利用已經比較過的資訊。在rabin-karp演算法中,使用模餘的辦法來減少比較的次數。先看**。

int rk_matcher(const char * txt, const char * pat,

int offset)

for (i = 0; i <= n - m; i++)

t = (t + q - (unsigned char)txt[i] * h % q) % q;

t = (d * t % q + (unsigned char)txt[i + m]) % q;

}return c;

}

rk演算法的關鍵在於,比較字串時先比較模餘值,如果一致再進行一字元一字元地比較,這樣避免了多數的無用比較。對於文字串「235902314526731」和模式串「31452」,取模13作為hash函式,對於23590首先計算模13的值為8,不等於31452模13的值5,故不用再做比較。第一次計算23590模13的值花費的時間為o(m),而第二次計算35902的值只需要花費o(1)的時間,35902 mod 13 = (((23590 mod 13) – (2 × 10000 mod 13)) × 10 + 2) mod 13。rk演算法正是通過模餘這個運算減少了比較的次數,使得演算法在一般情況下能達到o(n+m)的時間複雜度,最壞情況下時間複雜度依然是o(nm)。

knuth-morris-pratt演算法

kmp演算法是乙個非常經典的演算法,它完美地解決了重複比較的問題,演算法的時間複雜度下降到o(n),預處理時間為o(m)。

int kmp_matcher(const char * txt, const char * pat,

int offset)

for(i = 0, j = 0; i < n; i++)

delete next;

return c;

}

next陣列是kmp演算法中最重要的部分,它包含了匹配不成功後該移動的偏移資訊。舉個例子,對於模式串「abcfeabcd」,如果當前匹配到了模式串的第8個字元「c」時,文字串中下乙個字元與模式串中下乙個字元「d」不同,說明這次匹配失敗,但是不需要從模式串開始進行匹配,而可以從第四個字元「f」開始匹配。

boyer-moore演算法

bm演算法很類似kmp演算法,它與kmp的不同體現在模式串比較順序和遇到不匹配字元右移的距離所計算的方法不同,在一般情況下,它的效率要比kmp演算法高幾倍,但是在文字串和模式串具有週期性的情況下卻會退化到o(n^2),例如,當文字為ababababa,模式串為ababa時。此外,它需要的更多的儲存空間。對原始的bm演算法進行優化,可以使它在最壞情況下的時間複雜度也為o(n)。

int bm_matcher(const char * txt, const char * pat,

int offset)

int * gc = new int[m];

for (i = 0; i < m; i++)

gc[i] = m;

for (i = m - 1; i >= 0; i--)

if (sfx[i] == i + 1)

for (j = 0; j < m - i - 1; ++j)

if (gc[j] == m)

gc[j] = m - i - 1;

for (i = 0; i <= m - 2; ++i)

gc[m - 1 - sfx[i]] = m - i - 1;

for (i = 0; i <= n - m; i += a > b ? a : b) else

}delete sfx; delete gc; delete bc;

return c;

}

sunday演算法也是類似於kmp、bm的一種演算法,它在一般情況下的效率要比kmp和bm好,但是在極端情況下同bm演算法一樣會退化到樸素演算法的級別,這跟該演算法的具體實現有關。對原始sunday演算法進行優化,也可以使它在最壞情況下的時間複雜度降為o(n)。

int sunday_matcher(const char * txt, const char * pat,

int offset)

return c;

}

aho-corasick演算法是基於有限自動機的多模式串匹配演算法,這種演算法是基於trie的,它可以解決在一段文字中查詢指定的多個模式出現的位置,該演算法了構造乙個有限自動機,從而對文字串只需要進行一次遍歷即可。ac演算法的時間複雜度與構造有限自動機的時間和遍歷文字串的時間相關。

typedef struct trienodetrienode;

int trie_cnt = 0;

trienode trie[1000] = , 0, 0};

inline unsigned int ac_char2index(char c)

void ac_add_string(const char * sub)

else

}trie[i].flag = 1;

}void ac_build_automation()

}int ac_matcher(const char * txt, int offset)

return c;

寫幾個字串演算法

1 實現strstr函式 函式原型是char strstr char str1,char str2 作用是找出str2字串在str1字串中第一次出現的位置 不包括str2的串結束符 如果找到返回該位置的指標。若找不到,返回null指標。2 實現strcpy函式 char strcpy char de...

Oracle幾個字串函式

平常我們用oracle主要有兩種字串型別 1 char始終為固定的長度,如果設定了長度小於char列的值,則oracle會自動用空格填充的。當比較char時,oracle用空格將其填充為等長,再進行比較 2 varchar2資料型別為可變長度,雖然與varchar資料型別是同義的,但在今後的orac...

strcpy memcpy幾個字串函式的完美版

strcpy函式 char strcpy char strdest,const char strsrc memcpy函式 void memcpy void pvto,void pvform,size t size assert pvto null pvfrom null assert pbto pv...