LeetCode Algorithms 5. Longest Palindromic Substring 題解

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

找出給定字符串的最長迴文子串,首先想到使用暴力解法,第一層循環從字符串頭遍歷到尾,第二層循環從尾部開始到頭部,第三層循環檢驗是否是迴文。這樣的話時間複雜度很高,不做一些特殊情況的判斷就會TLE,以下貼出我的代碼:

string Solution::longestPalindrome(string s) {
    if (s.length() <= 1) return s;
    string res = "";
    int front, rear, forward;
    int end;
    for (int i = 0; i < (int)s.length(); i++) {
        forward = 0;
        front = i;
        end = rear = (int)s.length() - 1;
        while (front < rear) {
            while (s[front] == s[rear] && front <= rear) {
                front++;
                rear--;
                forward++; 
            }
            /* 找到迴文並且迴文比最長的迴文要長 */
            if (front >= rear && end - i + 1 > res.length()) {
                res = s.substr(i, end - i + 1);
                break;
            }
            rear = rear + forward - 1;
            front = i;
            end = rear;
            forward = 0;
        }
        if (res.length() >= s.length() - i) break; // 找到最長的迴文就跳出
    }
    if (res == "") {
        return s.substr(0,1);
    }
    return res;
}

很明顯,這樣做的話會有很多重複操作,浪費了時間,可以使用一個二維數組v[i][j]記錄從i個位置到第j個位置的字符串是否是迴文,如果是迴文,那麼去掉子串左右兩端後仍然是迴文,利用這個概念可以設計出dp轉移方程dp[i][j+i-1] = 1 if dp[i+1][j+i-2]==1,然後記錄子串頭尾位置即可。這樣可以把複雜度降到O(n^2)
代碼如下:

string Solution::longestPalindrome2(string s) {
    if (s.length() <= 1) return s;
    vector<vector<int>> dp(s.length(), vector<int>(s.length(), 0)); // dp[i][j]記錄從i到j是否爲迴文
    int len = 0;
    int start = 0, end = 0;
    dp[0][0] = 1;
    for (int i = 1; i < (int)s.length(); i++) {
        dp[i][i] = 1;
        dp[i][i - 1] = 1; // 子串長度爲2時,dp[i][i+1]與dp[i+1][i]同狀態
    }
    /* 枚舉迴文長度 */
    for (int subStrLen = 1; subStrLen < s.length(); subStrLen++) {
        /* 枚舉迴文開始位置 */
        for (int head = 0; head + subStrLen < s.length(); head++) {
            /* 迴文去掉左右端字符仍然是迴文 */
            if (s[head + subStrLen] == s[head] && dp[head + 1][head + subStrLen - 1]) {
                dp[head][head + subStrLen] = 1;
                if (subStrLen > end - start) {
                    start = head;
                    end = start + subStrLen;
                    break;
                }
            }
        }
    }
    return s.substr(start, end - start + 1);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章