/** * rk字符串匹配算法,主要引入了hash的概念, * 利用子串的hash值依次對比主串相應長度的子串hash值 * 並對hash值相同的子串進行匹配對比 */ public class RKSearch { /** * rk算法入口 * @param t 主字符串 * @param p 子字符串 * @return */ public int rk(String t,String p){ // 字符串非法判定 if (t == null||t.length() == 0 || p == null || p.length() == 0 || p.length() > t.length()){ return -1; } // 計算子串hash值 int hash = hash(p,26,31,0,p.length()); for (int i = 0;i< t.length();i++){ // 對主串內的數字一次進行hash計算,並對比子串是否匹配 if (hash(t,26,31,i,p.length()) == hash && match(t,p,i)){ return i; } } return -1; } /** * 自定義hash算法 * @param str * @param r 進制數 * @param k 將字符串映射到k的範圍 * @param start 從str串的開始位置 * @param len 子串的長度 * @return */ private int hash(String str,int r,int k,int start,int len){ int hash = 0; // 設定hash值爲0 /** * 對字符串內的每個字符串進行計算 */ for (int i = start;i<start+len;i++){ // 進制係數 與 hash 的積 + 每個字符與範圍取餘的結果 hash = (r * hash + str.charAt(i) % k); } // 將最後的結果,映射到指定範圍內 return hash % k; } /** * 對於hash計算結果相同的兩個子串,是否匹配的比較 * 主要判定hash衝突情況下的匹配問題 * @param t 主串 * @param p 子串 * @param i 從主串下標爲i的地方開始比較 * @return */ private boolean match(String t,String p,int i){ for (int j = 0 ; j < p.length();j++){ if (p.charAt(j) != t.charAt(j + i)){ return false; } } return true; } public static void main(String[] args) { String test = "adbsasdfddddsasdffesase"; String sub = "sd"; RKSearch rkSearch = new RKSearch(); int rk = rkSearch.rk(test, sub); System.out.println(rk); } }