周練(6)5. 最長迴文子串
阿新 • • 發佈:2020-10-14
/* * @lc app=leetcode.cn id=5 lang=cpp * * [5] 最長迴文子串 */ #include <iostream> #include <string> #include <cstdlib> #include <cstdio> using namespace std; // @lc code=start class Solution { public: //暴力解法:超時 // string longestPalindrome(string s) // { // int maxLen = 1; // int begin = 0; // int slen = s.length(); // for (int i = 0; i < slen - 1; ++i) // { // for (int j = i + 1; j < slen; ++j) // { // if (j - i + 1 > maxLen && validPalindromic(s, i, j)) // { // maxLen = j - i + 1; // begin = i; // } // } // } // return s.substr(begin, maxLen); // } // bool validPalindromic(string s, int left, int right) // { // while (left < right) // { // if (s[left] != s[right]) // { // return false; // } // left++; // right--; // } // return true; // } //動態規劃:一個迴文去掉兩頭,仍然是迴文 //狀態: dp[i][j] 表示子串s[i..j]是否是迴文子串 //得到狀態轉移方程: dp[i][j] = (s[i] == s[j]) and dp[i+1][j-1] // 邊界條件: j - 1 - (i + 1) + 1 < 2,整理得 j - i < 3 // 初始化dp[i][j] = true // 輸出.在得到一個狀態的值為true的時候,記錄起始位置和長0填表完成以後再擷取 string longestPalindrome(string s) { int slen = s.length(); if (slen < 2) { return s; } int maxLen = 1; int begin = 0; //dp[i][j] 表示 s[i..j] 是否是迴文串 [i, j] int dp[slen][slen]; for (int i = 0; i < slen; i++) { dp[i][i] = true; } // 注意:左下角先填 for (int j = 1; j < slen; j++) { for (int i = 0; i < j; i++) { if (s[i] != s[j]) // 先寫列 { dp[i][j] = false; } else { if (j - i < 3) // 長度<=2,沒必要再判斷 { dp[i][j] = true; } else { dp[i][j] = dp[i + 1][j - 1]; } } // 只要 dp[i][j] == true 成立, 就表示子串 s[i..j] 是迴文,此時記錄迴文長度和起始位置 if (dp[i][j] && j - i + 1 > maxLen) { maxLen = j - i + 1; begin = i; } } } return s.substr(begin, maxLen); } }; // @lc code=end