字串匹配演算法 蠻力演算法 KMP演算法 BM演算法

2021-09-03 02:37:13 字數 2323 閱讀 7547

子串:字串中任一連續的片段,稱作其子串(substring)

字首:prefix(s, k) = s.substr(0, k) = s[0, k)

字尾:suffix(s, k) = s.sbustr(n-k, k) = s[n-k, n)

串模式匹配(string pattern matching):

對基於同一字元表的任何文字t(|t| = n)和模式串p(|p| = m):

- 判定t中是否存在某一子串與p相等

- 若存在(匹配),則報告該字串在t串的起始位置

演算法1:

int match(char* p, char* t) 

else

}return i - j; //當(i-j)>m時,發現匹配,且p相對於t的對齊位置為i-j

}

演算法2:
int match(char* p, char* t) 

n(p, j) = \

n(p,j)

=一般地,該集合可能包含多個這樣的t,但需要注意的是,其中具體有哪些t構成,僅取決於模式串p以及前一輪比對的首個失配位置p[j],與文字串t無關。

int kmp(char* p, char* t)

else

j = next[j];

} delete next;

return i - j;

}

與蠻力演算法1相比,僅失配時演算法有所區別:kmp演算法此時保持i不變,從next表中取出乙個j來代替置零。注意if判斷條件多了乙個0可以看到,我們統一將n[0]賦值為-1,此處可假定在p[0]前面有乙個哨兵,該哨兵是乙個萬用字元,遇其必然進入if分支,該處相當於整個p在t[i]都沒有匹配的位置,因此要將p移動|p|步,並將i向右移動1步,即:

因此可以解釋為何kmp演算法中if判斷條件為何多了乙個。至此,我們簡單分析完了kmp演算法的策略與演算法實現,在buildnext**中,我們可以進一步優化,可改寫其為:

n[j] = (p[j] != p[t] ? t : n[t]);
其原因與正確性暫且不表。

我們僅需將目光放在演算法的迴圈部分:

while (i < n && j < m) 

else

j = next[j];

}

引入k = 2*i - j,對於if分支,i、j必然同時+1,則k必然會+1;對於else分支,i不變,next[j]必然至少會比j小1,則k至少也+1因此,k具有單調遞增的特性。再考慮最後k的範圍,其初始值為0,迴圈結束後有:

k =2

∗i−j

≤2∗(

n−1)

−(−1

)=2n

−1k = 2*i - j ≤ 2*(n-1) - (-1) = 2n - 1

k=2∗i−

j≤2∗

(n−1

)−(−

1)=2

n−1則得出結論,k單調遞增,且最大至o(n);算上buildnext所需要的時間,則kmp演算法時間複雜度為o(n+m)。

bm演算法中依然是將模式串p與文字串t從左開始對齊,但是卻是自模式串的右邊向左邊進行掃瞄對比。為實現高效率,bm演算法同樣是充分利用以往的資訊,使得p可以「安全的」往後盡可能多的移動。

int bm(char* p, char* t) 

delete gs;

delete bc;

if (i + strlen(p) <= strlen(t))

return i;

else

return -1;

}

bm演算法通過提前計算壞字元與好字尾的情況,從而在遇到時進行盡可能多的移動。

int* buildbc(char* p) 

int* buildgs(char* p)

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

gs[m - ss[j] - 1] = m - j - 1;

delete ss;

return gs;

}int* buildss(char* p)

} return ss;

}

如下圖,得出以上幾種演算法的效能分析。

蠻力演算法字串匹配

在這裡我們運用蠻力演算法解決,另外此問題還能用kmp演算法。該演算法的做法是將模式 也就是較短的子串,長度為m 對準文字 也就是較長的字串,長度為n 的前m個字元,從左到右匹配每一對相應的字元,如果有m對字元都匹配成功,那麼演算法停止,或者當遇到有一對不匹配時就將模式向右移一位,然後繼續從模式的第乙...

字串匹配 蠻力 KMP

前兩篇文章是從網上搜尋的,知道了next陣列可以有多種表示方法,但感覺kmp演算法詳解裡面第二種表示法給的程式有點小問題,今天自己改進了下,然後在leetcode strstr 上驗證了下,發現自己改進的程式可以ac,證明沒有問題 現在在這篇部落格中總結蠻力 kmp bm演算法的各種ac解法 蠻力法...

字元字串模式匹配演算法 BF演算法與KMP演算法

需解決的問題 從主字串s中尋找子字串t出現的第乙個位置?如果出現,返回pos,否則,返回 1 一 bf演算法 bf演算法就是樸素模式匹配演算法,即暴力求解,迴圈遍歷。將子字串的每個字元和主字串的字元按順序比較,如果比較不相等時,兩個字串的索引i和j同時回退,i回退到剛才主字串起始位置的下一位,子字串...