• 214. Shortest Palindrome



    July-14-2019
    还是挺难的,又过了一遍KMP.

    最直接的办法是楞做。
    abcd = > bcd abcd
    aacecaaa => a aacecaaa
    说白了就是找到给定String里面longest palindrome prefix。
    怎么找呢? 最直观的做法就是左右同时往中间,扫到相遇说明本身就是plindrome。
    失败的话,去掉右边最后一位, 重新扫,就是aacecaaa =>去掉最后一个A,继续扫 aacecaa然后发现满足。 这么做时间就爆炸了。

    一个稍微好点的办法是

        public String shortestPalindrome(String s) {
            if (s.length() <= 1) return s;
            
            int l = 0;
         
            for (int r = s.length() - 1; r >= 0; r --) {
                if (s.charAt(r) == s.charAt(l)) {
                    l ++;
                }
            }
            if (l == s.length()) return s;
            
            return new StringBuilder(s.substring(l)).reverse().toString() + shortestPalindrome(s.substring(0, l)) + s.substring(l);
        }
    }
    

    失败之后,继续,最后3个位置 0 - l - end来说,l-end肯定不符合规矩,需要翻转加到最前面,0-l不确定,只知道longest prefix palindrome肯定在这里面,所以继续recursively call。 其实这个也不好理解,我大概的理解是,每个LR的mismatch会让l最终到END的距离+1.

    刚才说道KMP,

    palindrome + something = S,我们要找的就是longest palindrome
    assuming palindrome of S = S·
    palindrome + something + something· + palindrome· = SS·
    palindrome = palindrome·
    这个问题变成了求SS·的最长 前缀=后缀,就是KMP的next[]干的事。
    不同的一点是,KMP里的NEXT可以让前缀后缀有overlap,比如aaaaa的最长前缀=后缀是aaaa而不是aa
    所以得保证我们generate KMP next[]的时候最长不能超过一半,有2个办法,一个是在SS`中间加个不存在与S中的字符,类似于S + "&" + S·这样每次OVERLAP都肯定会FAIL
    另一个办法是每次到了超过一半的位置就reset J,比较难理解,得深刻想明白为什么NEXT要那样GENERATE出来才能理解。

    class Solution {
        public String shortestPalindrome(String s) {
            if (s.length() <= 1) return s;
            
            int[] kmp = generateKmp(s + new StringBuilder(s).reverse().toString());
            
            int index = kmp[kmp.length - 1];
    
            return new StringBuilder(s.substring(index)).reverse().toString() + s;
            
        }
        
        public int[] generateKmp(String s) {
            if (s == null) return null;
            int[] res = new int[s.length()];
            
            int j = 0;
            for (int i = 1; i < s.length(); i ++) {
                if (i == s.length() / 2) j = 0;
                while (j != 0 && s.charAt(i) != s.charAt(j)) {
                    j = res[j - 1];
                }
                
                if (s.charAt(i) == s.charAt(j)) {
                    j ++;
                }
                
                res[i] = j;
            }
            return res;
        }
    }
    
  • 相关阅读:
    Custom Settings.in 配置信息收集
    DPM恢复点和保持期、常见问题排除指南
    裸机恢复 (BMR) 和系统状态恢复
    远程桌面开启(命名空间)
    RPC终结点映射
    远程计算机 进程/服务 启动停止(WMI)
    环境变量、语言类型转换、静态类、字符串
    密封管理包
    PowerShell管理SCOM2007R2
    PowerShell管理SCOM_批量设置维护模式(上 )
  • 原文地址:https://www.cnblogs.com/reboot329/p/6060573.html
Copyright © 2020-2023  润新知