給出字串p和t,長度分別為n和m。找出p在t中出現的所有位置。
在3.2和3.3節中,給出了2個移動的位置。在boyer-moore演算法中,取2個值中的最大值。int index(char* p,char* t,int pos)
suffix tree演算法需要對字串t進行預處理,而boyer-moore演算法和kmp演算法需要對p進行預處理。所以,suffix tree比較適合t不變,p變化的場景。boyer-moore演算法和kmp演算法適合t變化,p不變的場景。本文即是對boyer-moore演算法的理論性介紹。else
}if(j> strlen(p)) return (i – strlen(p) + 1);
else return -1;
}
在進行一次的匹配過程中,掃瞄p是從右向左的。如下圖,在第一次的匹配過程中,首先比較p[7]和t[7],然後比較p[6]和t[6],從右向左滑動。
見圖2。第一次比較:t[7](=x) ≠ p[7](=a),結果是不匹配,此時如果我們知道x在p中出現的right-most位置為4,就可以移動p至圖3中所示的位置。
定義:字符集中的任一字元x,r(x)表示在p中出現的right-most位置,如果x沒有在p中出現,則r(x)置為0。計算r(x)的時間複雜度為o(n)。
壞字元規則:
在某次匹配過程中,p的最右邊的 n-i 個字元已經和t中的匹配,但是第i個字元不匹配(對於t中的第k個字元),此時p應該向右移動 max( 1, i – r(t[k]) )。
壞字元規則在實際應用中特別高效。但是如果字符集比較小,則效率較差,時間複雜度達不到線型。
好字尾規則:
在某次的匹配過程中,p的乙個字尾匹配了t中的的子串t,但是子串t左邊的第乙個字元不匹配,如果p中存在滿足如下條件的子串t`:
1 t`=t,但t`不是p的字尾
2 在p中位於t`左邊的第乙個字元 ≠ 在p中位於t左邊的第乙個字元
3 在滿足第1,2條件下,在p中位置處於最右的t`
則移動p使得t` 與t中的t對齊,如圖5所示。如果不存在,則向右移動p最少距離,使得p的某個字首匹配t中的t的某個字尾,如圖6。如果還沒有匹配的,則p向右移動n個位置,如圖7。
【定義】
對於任一i∈(1,n),l(i) 是滿足下列條件的值:
1 l(i) < n
2 字串p[i…n] 匹配p[1…l(i)]的字尾
3 如果存在滿足條件1和2的情況,則取最大值 ,否則取值為0
【定義】
nj(p)是 滿足如下字串的長度:
1 是p[1…j]的字尾
2 是p的字尾
3 滿足條件1,2的最長字串
【定理】
l(i) 是 滿足條件nj(p) = |p[i…n]|= n–i +1 的j的最大值。
根據如上定理,計算l(i)的演算法如下:
for i:=1 to n do l(i) := 0;
for j:=1 to n-1 do
begin
i:=n - nj(p) + 1;
l(i) = j;
end;
在壞字元規則中,計算r(x)的時間複雜度為o(n);在好字尾規則中,計算l(i)的時間複雜度為o(n)。所以boyer-moore演算法的時間複雜度為o(m+n)。
假設主串為s1 s2 …sn 模式串為p1 p2…pm 。當匹配過程中產生失配(即si≠pj)時,模式串向右滑行多遠,換句話說,當主串第i個字元與模式串中的第j個字元發生失配時,主串中的第i個字元(i指標不回溯)應用與模式中的哪個字元比較?
next[j] = 0 當j=1
= max{k| 1=1 其它情況
複雜度分析。計算next陣列的複雜度為o(m),所以最終匹配的複雜度為o(m+n)。
查詢字串
在乙個主串中查詢相應的子串,如 abcdwoshidef 中查詢 woshi 方法 該實現的方法是最簡單的模式匹配方法,時間複雜度較高 include iostream using namespace std int searchstring const char str1,const char s...
查詢字串
qstring startwith 判斷乙個字串是否以某個字串開頭,引數 字串,大小寫敏感 qstring str welcome to you str.startswith welcome qt casesensitive 返回true str.startswith you qt casesens...
查詢字串
本身不難,寫到這裡只是乙個備忘錄的作用。假定linux系統中有乙個目錄,其中遞迴的存在若干子目錄。現在需要在這些目錄的檔案中尋找乙個字串marvel。我看到的方法是 find type f exec grep marvel 可是死活就是錯誤 find missing argument to exec...