虽是读书笔记,但是如转载请注明出处 http://segmentfault.com/blog/exploring/
.. 拒绝伸手复制党


最长回文子串

题目描述

给定一个字符串,求它的最长回文子串的长度。

also Leetcode 5

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.

解法1 暴力解法

暴力解法,枚举所有子串,对每个子串判断是否为回文,复杂度为 O(n^3)。
这个思路初看起来是正确的,但却做了很多无用功,如果一个长的子串包含另一个短一些的子串,那么对子串的回文判断其实是不需要的。

解法2 动态规划

寻找一个字符串的重复子串 LRS
算法设计 - LCS 最长公共子序列 && 最长公共子串 &&LIS 最长递增子序列
这些问题有一个DP算法,可以实现O(n^2)时间内解决问题
P.S. 这种做法leetcode是不接受的...超过时间限制

    public String longestPalindrome(String s){
        if(s.length()==0){
            return "";
        }
        if(s.length() == 1)
        {
            return s;
        }
         boolean[][] dp =new boolean[s.length()][s.length()];
         for(int i=0;i<s.length();i++){         
             for(int j=0;j<s.length();j++){
                 if(j<=i)
                     dp[i][j] = true; //当i == j 的时候,只有一个字符的字符串; 当 i > j 认为是空串,也是回文
                 else
                     dp[i][j] = false;
             }
         }  

        int maxlen = 1;
        int pstart = 0, pend = 0;
        // 第一层循环,k为枚举子串长度-1
         for(int k=1; k<s.length(); k++){
             // 第二层循环,i为子串起始位置,dp[i][j] 
             // 表示以第i个元素开始,第j个元素为尾的的字符串是否是回文;j = i+k
             for(int i=0; k+i<s.length(); i++){
                 int j = i+k;
                 if(s.charAt(i) == s.charAt(j)){
                     dp[i][j] = dp[i+1][j-1];
                     if(dp[i][j]){
                        if(k + 1 > maxlen)
                        {
                            maxlen = k + 1;
                            pstart = i;
                            pend= j;
                        }
                     }
                 }
                 else{
                     dp[i][j] = false;
                 }

             }       
         }
         return s.substring(pstart, pend+1);
    }

Manacher 算法

进一步优化,Manacher 算法的时间复杂度O(n)
useful links
July 讲解
mark 以后看

Appendix

基于 “最长回文子串算法”求一个字符串的最小回文划分


Leetcode-Add Binary


Given two binary strings, return their sum (also a binary string).
For example,
a = "11"
b = "1"
Return "100".

二进制相加,字符串输入,字符串输出

public class Solution {
    public String addBinary(String a, String b) {
        StringBuffer binary = new StringBuffer(); 
        int la = a.length()-1;
        int lb = b.length()-1;
        int digit = 0;
        while(la>=0 && lb>=0){
            int n = a.charAt(la) - '0';
            int m = b.charAt(lb) - '0';         

            if(n + m + digit >= 2){
                binary.insert(0, n + m + digit -2);
                digit = 1;
            }
            else{       

                binary.insert(0, n + m + digit);
                digit = 0;
            }               
            la--;
            lb--;
        }
        while(la>=0){
            int n = a.charAt(la)  - '0';
            if(n + digit >= 2){         
                binary.insert(0, n + digit-2);
                digit = 1;
            }
            else{           
                binary.insert(0, n +digit);
                digit = 0;
            }               
            la--;
        }

        while(lb>=0){       
            int n = b.charAt(lb) - '0';
            if(n + digit >= 2){
                binary.insert(0, n + digit -2);
                digit = 1;
            }
            else{           
                binary.insert(0, n +digit);
                digit = 0;
            }               
            lb--;
        }
        if(digit ==1){
            binary.insert(0, 1);
        }
        return binary.toString();
    }
}

觉得这个代码太冗杂,有三块实现的是同样的功能,完全可以优化;
想起了《算法导论》讲归并排序 merge两个长短不同序列优化代码的方法:哨兵。
那这块完全可以加入哨兵,短的字符串,当遍历完,空出来的位置就都设置为0

然后直接用两个 index 一起往前跑就好了
clipboard.png

public class Solution {
       public String addBinary(String a, String b) {
        StringBuffer binary = new StringBuffer(); 
        int la = a.length()-1;
        int lb = b.length()-1;
        int digit = 0;

        for(int i=la, j = lb;i>=0||j>=0;i--,j--){
            int ai = i>=0? a.charAt(i) - '0' : 0; // 哨兵
            int bj = j>=0? b.charAt(j) - '0' : 0; // 哨兵
            int val = (ai + bj + digit) %2;
            System.out.println("val" +val);
            digit = (ai + bj + digit) /2;
            binary.insert(0, val);
        }
        if(digit == 1){
            binary.insert(0, 1);
        }

        return binary.toString();
    }
}

clipboard.png


SecondLife
1.9k 声望252 粉丝