hash 值重复_“重复”相关的问题
生活随笔
收集整理的這篇文章主要介紹了
hash 值重复_“重复”相关的问题
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
重復子串比較的核心是使用 Rabin-Karp (Rolling Hash)。
Rabin-Karp字符串編碼的本質是對字符串進行哈希,將字符串之間的比較轉化為編碼之間的比較有N個不同的字符,可以將字符組成的串,映射成 N進制表示的10進制數。每一個數可以代表一種字符。 去頭加尾的哈希計算可以在
的時間內完成題目A(困難)
1044. 最長重復子串給出一個字符串 S,考慮其所有重復子串(S 的連續子串,出現兩次或多次,可能會有重疊)。
返回任何具有最長可能長度的重復子串。(如果 S 不含重復子串,那么答案為 ""。)示例 1:輸入:"banana" 輸出:"ana" 示例 2:輸入:"abcd" 輸出:""
二分查找 + Rabin-Karp 字符串編碼
子任務一:二分查找
如果字符串中存在長度為 L 的重復子串,那么一定存在長度為 K < L 的重復子串(選取長度為 L 的重復子串的某個長度為 K 的子串即可),因此我們可以使用二分查找的方法,找到最大的 L。
子任務二:是否存在長度為L的重復子串(Rabin-Karp 字符串編)
使用 Rabin-Karp 算法將字符串進行編碼,這樣只要有兩個編碼相同,就說明存在重復子串。
對于選取的長度 L:使用長度為 L 的滑動窗口在長度為 N 的字符串上從左向右滑動;
哈希計算公式字符一共有26,a最小可以取26.
檢查當前處于滑動窗口中的子串的編碼是否已經出現過(用一個集合存儲已經出現過的編碼)。若已經出現過,就說明找到了長度為 L 的重復子串;若沒有出現過,就把當前子串的編碼加入到集合中。
注意事項:取模
最后一個需要解決的問題是,在實際的編碼計算中,hash值、
可能會非常大,在 C++ 和 Java 語言中,會導致整數的上溢出。所以,需要對編碼值進行取模,將編碼控制在一定的范圍內,防止溢出,即h = h % modulus。h = (h * a - nums[start - 1] * aL % modulus + modulus) % modulus; h = (h + nums[start + L - 1]) % modulus;注意事項2:哈希沖突
取模會導致哈希沖突,既是有可能兩個字符串是不同的,但是哈希值相同。后續的話學習一下hash沖突的解決方式。
最終代碼
public int search(int L, int n, int[] nums) {// roll hash的base值,26個字符,用26進制玩。int a = 26;// 防止hash值溢出,使用的mod數long modulus = (long) Math.pow(10, 16);// 計算長度為L的第一個子串的 roll hash 值long h = 0;for (int i = 0; i < L; ++i)h = (h * a + nums[i]) % modulus;// 存儲已出現過的hash值HashSet<Long> seen = new HashSet<>();seen.add(h);// 第一位的26的L冪 取模 : aL % moduluslong aL = 1;for (int i = 1; i <= L; ++i)aL = (aL * a) % modulus;for (int start = 1; start < n - L + 1; ++start) {// compute rolling hash in O(1) timeh = (h * a - nums[start - 1] * aL % modulus + modulus) % modulus;h = (h + nums[start + L - 1]) % modulus;if (seen.contains(h)) return start;seen.add(h);}return -1;}public String longestDupSubstring(String S) {int n = S.length();// 將字符串映射成 hash值 (26進制的數值)// 實現常數時間復雜度的滑動窗口int[] nums = new int[n];for (int i = 0; i < n; ++i)nums[i] = (int) S.charAt(i) - (int) 'a';// 二分搜索, L = 要定位的重復字符串的長度int minRepeat = 1, maxRepeat = n;int L;while (minRepeat != maxRepeat) {L = minRepeat + (maxRepeat - minRepeat) / 2;if (search(L, n, nums) != -1)minRepeat = L + 1;elsemaxRepeat = L;}int start = search(minRepeat - 1, n, nums);return start != -1 ? S.substring(start, start + minRepeat - 1) : "";}總結
以上是生活随笔為你收集整理的hash 值重复_“重复”相关的问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 方舟原始恐惧代码_源代码分支管理模式丨中
- 下一篇: python最适合做什么生意赚钱投资小_