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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章