rk演算法是rabin-karp演算法的簡稱,是經典的字串匹配演算法,在《演算法導論》上是有介紹的,有興趣的同學可以去看看。
rk演算法的複雜度可以說是比上不足比下有餘,比一般的匹配演算法要好,但是又比不上kmp,sunday等演算法。演算法表現跟快排比較相似,演算法平均複雜度表現較好,但最壞情況時複雜度會相對較高。
rk演算法的核心思想類似於hash函式。對於hash函式有了解的同學應該知道,我們通過hash函式可以將乙個字串對映成乙個數字(hash值)。當兩個字串的hash值不相同時,說明這兩個字串一定不匹配,而相同時則說明兩個字串是有可能匹配的,那麼就需要進一步驗證。
首先給兩個字串,假設str長度為n,pattern長度為m:
char str=;
char pattern=;
我們利用下面的公式可以用pattern計算出乙個值x:
d=26;
l=p.length;
x=p[l-1]+d*(p[l-2]+d*(p[l-3]+...+(p[1]+d*p[0])));
把pattern帶入上面p中,可以求出乙個值pattern_x,這個值就是代表pattern的hash值,或者說是對映值。d的取值根據字串字元的所有可能性值的數量來分配。比如數字0~9,此時d=10,又如字母a~z,此時d=26。
我們可以在str中找到 (n-m+1) 個長度與pattern相同的子串str_sub=,如下:
char str=;
char st1=;
char st2=;
...char st(n-m+1)=;
然後利用上面的公式就計算出這些子串的對映值,與pattern的對映值進行比較後,排除與pattern_x 不相同的對映值,留下相同的值,再取出子串和pattern之間進行字元比較,判斷是否匹配。
還有乙個小問題,就是當pattern較長的時候,pattern_x會比較大,可能會超過最大長度範圍。這時只要取乙個素數q,計算的時候對對映值取餘即可解決這個問題。q取素數會比較好,一般滿足q*d好了,來看**吧
//驗證兩個字串是否相同
bool ismatching(char *str,char *pattern)
} return true;
}//主函式
bool fun(char *str, char *pattern)
//字串開始匹配,對p_code和s_code 進行比較,並更新s_code的值
for (int i = 0; i < size1 - size2+1; i++)
//更新s_code,去掉開頭的值str[i],加上str[i+size2]
s_code = ((s_code - h * (str[i] - 'a'))*d + str[i + size2] - 'a') % q;
} return false;
}
更新str子串對映值可能會稍微難理解一些,舉個例子:
char str=;
char st1=;
char st2=;
st1和st2中間的部分一致,僅首尾變化了,那麼可以推出:
st1_x-st1[0]*pow(d,m-1)%q=(st2_x-st2[m-1])/d;
st2_x=((st1_x-st1[0]*pow(d,m-1)%q)*d+st2[m-1])%q;
st1_x,st2_x為對映值。也就有了我上面**中的公式:
s_code = ((s_code - h * (str[i] - 'a'))*d + str[i + size2] - 'a') % q;
好了,不早了,休息去了~~~~ 字串匹配KMP演算法學習筆記
字串匹配,leetcode28題。時間複雜度o mn 的演算法大家都會,題解裡面官方賬號給出的利用字串雜湊判等的o n 演算法也很優秀。本篇的重點是kmp演算法。如果還不是很好理解,可以看labuladong的題解。乙個kmp演算法易理解版本,講解的部分也很清楚。本篇主要是對此題解做乙個補充,個人感...
字串模式匹配 BF演算法和RK演算法
bf演算法 暴力匹配演算法,也叫樸素匹配演算法 效能不是很高。我們在主串中,檢查起始位置分別是0.1.2 n m且長度為n m 1個子串,看有沒有跟模式串匹配的。在a中查詢b,a就是主串,b就是模式串,且a b 最壞的時間複雜度為o n m 但是實際上,這也是常用的,1.模式串和主串的長度都不會太長...
字串演算法學習筆記(三)
回文字串是指正序和反序以向的字串 定義前後指標,看你對應的位置是不是一樣 bool judge string a,int size int front 前指標 int end 後指標 front 0 初始指向字串的頭 end size 1 初始指向字串的尾 while front end front...