Leetcode - Longest Palindrome Substring

5972 ワード


Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.
[balabala]Method 1小さい頃から大きいまで一つ一つ異なる長さのサブストリングが回文かどうかをチェックし、DPを使って中間計算を保存していたが、タイムアウトしてしまう.Method 3は非DP版のMethod 1で、1年前の歴史記録はAcceptだった.当時leetcodeは居眠りをしていたと推定される.Method 2は同様にDPであり、Acceptされ、解析計算回数はMethod 1と同様にEclipseで実際にタイムアウトしたcaseを実行することができ、後者は前者より3、4 ms速く、違いは主にMethod 1が配列にアクセスするモードがMethod 2より優れていないため、2次元配列を1つの行列と見なし、Method 1は各行間でジャンプしてアクセスし続け、Method 2は1回の外層サイクルで同じ行の配列に1列ずつアクセスするためであると考えられる.Method 4は、現在の1文字または現在の2文字から両側に放射された最長の回文であり、この方法はMethod 2よりも効率が高い.これは、「abcdefg」などの無意味な計算を回避するため、Method 1および2はすべてのサブストリングを計算する必要があるが、Method 4はabcdeのようなサブストリングを計算することはなく、bcdを計算する際にcを中心とした残りのサブストリングの計算を停止する.もう一つ
O(n)の実現は、まだ理解されていませんが、
http://www.cnblogs.com/tenosdoit/p/3675788.htmlは忘れておきます.
[ref]
http://www.cnblogs.com/tenosdoit/p/3675788.html
http://www.cnblogs.com/jdflyfly/p/3810674.html
http://codeganker.blogspot.com/2014/02/longest-palindromic-substring-leetcode.html

// Method 1: O(n^2), time out
    public String longestPalindrome1(String s) {
        if (s == null || s.equals(""))
            return "";
        int n = s.length();
        boolean[][] dp = new boolean[n][n];
        for (int i = 0; i < n; i++)
            dp[i][i] = true;
        String ans = s.substring(0, 1);
        for (int i = 0; i < n - 1; i++) {
            dp[i][i + 1] = s.charAt(i) == s.charAt(i + 1);
            if (ans.length() == 1 && dp[i][i + 1])
                ans = s.substring(i, i + 2);
        }
        
        for (int l = 3; l <= n; l++) {
            for (int i = 0; i + l <= n; i++) {
                int j = i + l - 1;
                dp[i][j] = s.charAt(i) == s.charAt(j) && dp[i + 1][j - 1];
                if (ans.length() < l && dp[i][j])
                    ans = s.substring(i, i + l);
            }
        }
        return ans;
    }
    
    // Method 2: O(n^2)  DP 
    // http://codeganker.blogspot.com/2014/02/longest-palindromic-substring-leetcode.html
    public String longestPalindrome(String s) {
        if (s == null || s.equals(""))
            return "";
        int n = s.length();
        String ans = "";
        int maxLen = 0;
        boolean[][] dp = new boolean[n][n];
        for (int i = n - 1; i >= 0; i--) {
            for (int j = i; j < n; j++) {
                if (s.charAt(i) == s.charAt(j) && (j - i < 2 || dp[i + 1][j - 1])) {
                    dp[i][j] = true;
                    if (maxLen < j - i + 1) {
                        maxLen = j - i + 1;
                        ans = s.substring(i, j + 1);
                    }
                }
            }
        }
        return ans;
    }
    
    // Method 3: O(n^2), from up to bottom, once accept, time out now
    public String longestPalindrome3(String s) {
        if (s == null || s.equals(""))
            return "";
        int n = s.length();
        for (int len = n; len >= 1; len--) {
            for (int i = 0; i + len <= n; i++) {
                String sub = s.substring(i, i + len);
                if (isPalin(sub)) {
                    return sub;
                }
            }
        }
        return "";
    }
    private boolean isPalin(String s) {
        int i = 0, j = s.length() - 1;
        while (i < j) {
            if (s.charAt(i) != s.charAt(j))
                return false;
            i++;
            j--;
        }
        return true;
    }
    
    // Method 4: O(n^2)  
    // http://www.cnblogs.com/jdflyfly/p/3810674.html
    public String longestPalindrome4(String s) {
        if (s == null || s.equals(""))
            return "";
        int n = s.length();
        int maxLen = 1;
        int tmpLen = 0;
        String ans = s.substring(0, 1);
        for (int i = 0; i < n - 1; i++) {
            tmpLen = getPalin(s, i - 1, i + 1);
            if (tmpLen > maxLen) {
                int start = i - tmpLen / 2;
                ans = s.substring(start, start + tmpLen); 
                maxLen = tmpLen;
            }
            tmpLen = getPalin(s, i, i + 1);
            if (tmpLen > maxLen) {
                int start = i - tmpLen / 2 + 1;
                ans = s.substring(start, start + tmpLen);
                maxLen = tmpLen;
            }
        }
        return ans;
    }
    
    private int getPalin(String s, int left, int right) {
        int n = s.length();
        int len = right - left - 1;
        while (left >= 0 && right < n) {
            if (s.charAt(left--) == s.charAt(right++)) {
                len += 2;
            } else {
                return len;
            }
        }
        return len;
    }