标签:span 一个 单个字符 就是 code view 检索 pre 构造
1、动态规划
首先单个字符就是一个回文子串,如果两个字符都相同就是一个回文子串,三个字符是在一个字符的左右两边加上相同字符而成的回文子串,四个字符是两个字符左右两边加上相同字符形成的回文子串。
不妨以单个字符和双个字符为初始条件去构造动态方程:
dp[i][i]=1;//单个字符
dp[i][i+1]=1; (s[i]=s[i+1])
1 class Solution { 2 public: 3 string longestPalindrome(string s) { 4 int len=s.size(); 5 if(len==0||len==1) 6 return s; 7 int start=0;//回文串起始位置 8 int max=1;//回文串最大长度 9 vector<vector<int>> dp(len,vector<int>(len));//定义二维动态数组 10 for(int i=0;i<len;i++)//初始化状态 11 { 12 dp[i][i]=1; 13 if(i<len-1&&s[i]==s[i+1]) 14 { 15 dp[i][i+1]=1; 16 max=2; 17 start=i; 18 } 19 } 20 for(int l=3;l<=len;l++)//l表示检索的子串长度,等于3表示先检索长度为3的子串 21 { 22 for(int i=0;i+l-1<len;i++) 23 { 24 int j=l+i-1;//终止字符位置 25 if(s[i]==s[j]&&dp[i+1][j-1]==1)//状态转移 26 { 27 dp[i][j]=1; 28 start=i; 29 max=l; 30 } 31 } 32 } 33 return s.substr(start,max);//获取最长回文子串 34 } 35 };
2、中心扩展法
思路就是回文子串可以从他的中心进行扩展,并且只有 2n-1 个这样的中心(一个元素为中心的情况有 n 个,两个元素为中心的情况有 n-1 个)
假如回文的中心为 双数,例如 abba,那么可以划分为 ab bb ba,对于n长度的字符串,这样的划分有 n-1 种。
假为回文的中心为 单数,例如 abcd, 那么可以划分为 a b c d, 对于n长度的字符串,这样的划分有 n 种。
对于 n 长度的字符串,我们其实不知道它的回文串中心倒底是单数还是双数,所以我们要对这两种情况都做遍历,也就是 n+(n-1) = 2n - 1,所以时间复杂度为 O(n)。
当中心确定后,我们要围绕这个中心来扩展回文,那么最长的回文可能是整个字符串,所以时间复杂度为 O(n)。
所以总时间复杂度为 O(n^2)
1 string longestPalindrome(string s) 2 { 3 if (s.length() < 1) 4 { 5 return ""; 6 } 7 int start = 0, end = 0; 8 for (int i = 0; i < s.length(); i++) 9 { 10 int len1 = expandAroundCenter(s, i, i);//一个元素为中心 11 int len2 = expandAroundCenter(s, i, i + 1);//两个元素为中心 12 int len = max(len1, len2); 13 if (len > end - start) 14 { 15 start = i - (len - 1) / 2; 16 end = i + len / 2; 17 } 18 } 19 return s.substr(start, end - start + 1); 20 } 21 22 int expandAroundCenter(string s, int left, int right) 23 { 24 int L = left, R = right; 25 while (L >= 0 && R < s.length() && s[L] == s[R]) 26 {// 计算以left和right为中心的回文串长度 27 L--; 28 R++; 29 } 30 return R - L - 1; 31 }
标签:span 一个 单个字符 就是 code view 检索 pre 构造
原文地址:https://www.cnblogs.com/nxnslc-blog/p/12454987.html