美文网首页
1044. Longest Duplicate Substrin

1044. Longest Duplicate Substrin

作者: 尚无花名 | 来源:发表于2019-05-13 06:31 被阅读0次

    这道就是Rolling Hash + Binary Search的组合。
    周赛的时候笔者想到了Rolling Hash, 然后并没有想到加binary search进行优化
    写了两个naive的solution 都TLE了,然而虽然这题没写出来,这次周赛还是排在300名左右不算差。
    要 对Rolling hash再熟一点,我下来之后写的代码在减去最高位的时候出一个bug调了好久。
    当减去最高位时, 我傻傻的直接mod (26 ** len)了。
    应该是减去 (26 ** len) 再mod (MOD).
    不能mod (26 ** len)的。

    The idea is similar to Lee215's post.
    Using rolling hash to avoid recalculation of the hash key.
    Using binary search to find the longgest length.

    class Solution {
        Long MOD;
        public String longestDupSubstring(String S) {
            int N = S.length();
            int max = 0;
            String ans = "";
            MOD = 1000000007L;
            int l = 0, r = N - 1; 
            //binary search 
            
            while (l <= r) {  
                int mid = l + (r - l) / 2;          
                boolean breakout = false;
                Map<Long, List<Integer>> map = new HashMap<>(); // the List<Integer> store a list of indexes which have the same hashCode
                long prev = 0;
                long pow26 = calcPower26(mid);
                for (int i = 0; i + mid - 1 < N; i++) {
                    long code = calc(S, i, mid, prev, pow26); // calculate hashcode
                    if (map.containsKey(code)) {
                        for (int m : map.get(code)) { // iterate thru the list and verify the match to deal with hash collision.
                            if (S.substring(i, i + mid).equals(S.substring(m, m + mid))) {
                                breakout = true;
                                if (mid > max) {
                                    max = mid;
                                    ans = S.substring(i, i + mid);
                                }
                                break;
                            }
                        }
                    }
                    if (breakout) break;
                    map.putIfAbsent(code, new ArrayList<>());
                    map.get(code).add(i);
                    prev = code; //log prev for next hashcode calculation.
                }
                if (breakout) l = mid + 1;
                else r = mid - 1;
            }
            return ans;
        }
        private long calc(String s, int start, int len, long prev, long pow26) {
            long ans = 0L;
            if (start == 0) { // first time calcuation
                for (int i = 0; i < len; i++) {
                    ans *= 26L;
                    ans += (long) (s.charAt(start + i) - 'a');
                    ans %= MOD;
                }
            } else { // defer from previous result.
                ans = prev * 26L;
                ans += (long) (s.charAt(start + len - 1) - 'a');
                ans -= (s.charAt(start - 1) - 'a') * pow26;    // 在这里写了一个bug, 我直接用ans % pow26了。
            }
            ans %= MOD;
            if (ans < 0L) ans += MOD;
            return ans;
        }
        private long calcPower26 (int n) {
            if (n == 0) return 1L;
            if (n == 1) return 26L;
            long half = calcPower26( n / 2);
            long ans = (half * half) % MOD;
            ans *= calcPower26(n - (n / 2) * 2);
            return ans % MOD;
        }
        
    }
    

    相关文章

      网友评论

          本文标题:1044. Longest Duplicate Substrin

          本文链接:https://www.haomeiwen.com/subject/biskaqtx.html