求字符串的最長迴文串-----Manacher's Algorithm 馬拉車算法

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

Example 1:

Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.

Example 2:

Input: "cbbd"
Output: "bb"

思路一:求每一個子串,但是要知道一個技巧就是如何截取從最大串到最小串的判斷。時間複雜度是O(N^3)

class Solution {
    public String longestPalindrome(String s) {

        //O(N^3)的時間複雜度
        if(s.length() <= 1)
            return s;
        for(int i = s.length(); i >= 0; i--)
        {
            for(int j = 0; j <= s.length() - i; j++)
            {
                //關鍵在於這個截取的子串,由長到短,這個是最關鍵的
                String subStr = s.substring(j, i+j);//從外向內收縮的子串,截取的子串越來越短
                int count = 0;
                for(int k = 0; k < subStr.length()/2; k++)
                {
                    if(subStr.charAt(k) == subStr.charAt(subStr.length() - k -1))//判斷是不是迴文
                        count++;
                }
                 if(count == subStr.length() / 2)//第一次出現的迴文就是最長的
                     return subStr;
            }
           
        }
        return "";
        }
 } 

思路二:馬拉車算法,時間複雜度爲O(N),具體算法過程看這裏:Manacher’s Algorithm 馬拉車算法

class Solution {
    public String longestPalindrome(String s) {
        //馬拉車算法O(N)的時間複雜度
        if(s.length()==0)
            return "";
        StringBuilder t = new StringBuilder("$#");
        for(int i = 0; i < s.length(); i++)
        {
            t.append(s.charAt(i));
            t.append('#');
        }
        t.append('@');
        int[] p = new int[t.length()];
        int mx = 0;
        int id = 0;
        int resLen = 0;
        int resCenter = 0;
        for(int i = 1; i < t.length()-1; ++i)
        {
        	//關鍵算法步驟
            p[i] = mx > i ? Math.min(p[2 * id - i], mx - i) : 1;
            //如果對稱點的長度比當前的還長,後面的是否匹配要自己去算
            while (((i - p[i])>=0) && ((i + p[i])<t.length()-1) 
            		&& (t.charAt(i + p[i]) == t.charAt(i - p[i])))
            		 			++p[i];
            if (mx - i <  p[i]) {
                mx = i + p[i];
                id = i;
            }
            if (resLen < p[i]) {
                resLen = p[i];
                resCenter = i;
                }   
        }
        
        return s.substring((resCenter - resLen) / 2,(resCenter - resLen) / 2 + resLen - 1);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章