【leetcode】Longest Palindromic Substring
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, and there exists one unique longest palindromic substring.
Hide Tags
String利用DP思想做
dp[i][j]表示了第字符串中,s[i,i+1,……, j]是否是回文
可以有以下递推公式:
if(i==j) dp[i][j]=true;
if(i-j=1)dp[i][j]=s[i]==s[j];
if(i-j>1)dp[i][j]=dp[i+1][j-1]&&s[i]==s[j]
1 class Solution { 2 public: 3 string longestPalindrome(string s) { 4 5 int n=s.length(); 6 //采用vector会超时 7 //vector<vector<bool> > dp(n,vector<bool>(n)); 8 bool dp[1000][1000]={false}; 9 int maxDis=-1; 10 int start; 11 int end; 12 int dis; 13 for(int i=n-1;i>=0;i--) 14 { 15 for(int j=i;j<n;j++) 16 { 17 if(s[i]==s[j]) 18 { 19 dis=j-i; 20 if(dis==0||dis==1||dp[i+1][j-1]&&dis>1) 21 { 22 dp[i][j]=true; 23 if(dis>maxDis) 24 { 25 maxDis=dis; 26 start=i; 27 end=j; 28 } 29 } 30 } 31 } 32 } 33 return s.substr(start,end-start+1); 34 } 35 };
一种O(n)的算法:
算法的思想就是根据前面串的对称情况,在寻找后面的对称串时,可以跳过不必要的比较
先在每两个相邻字符中间插入一个分隔符,当然这个分隔符要在原串中没有出现过。一般可以用‘#’分隔。这样就非常巧妙的将奇数长度回文串与偶数长度回文串统一起来考虑了(见下面的一个例子,回文串长度全为奇数了)
在比较的时候为了防止越界,可以再在字符串左右两边添加"^"和'$'
例如abb
^#a#b#b#$
P[id]记录的是以字符str[id]为中心的最长回文串,当以str[id]为第一个字符,这个最长回文串向右延伸了P[id]个字符
这里有一个很好的性质,P[id]-1就是该回文子串在原串中的长度(包括‘#’)
我们用mx记在i之前的回文串中,延伸至最右端的位置。同时用id这个变量记下取得这个最优mx时的id值。
如果i正好在某个回文串内部,则寻找与他对称的位置的元素的回文串的长度p[j],如果p[j]没有超出改回文串的内部,如下图所示,那么p[i]=p[j]
如果超出了,则取p[i]=mx-i
1 class Solution { 2 3 public: 4 string longestPalindrome(string s) { 5 6 int n=s.length(); 7 int id=0; 8 int right=0; 9 int i; 10 11 string pre_s; 12 pre_s="^#"; 13 for(int i=0;i<n;i++) 14 { 15 pre_s=pre_s+s[i]+'#'; 16 } 17 pre_s+='$'; 18 19 20 int n1=pre_s.length(); 21 22 vector<int> p(n1); 23 24 for(i=1;i<n1-1;i++) 25 { 26 if(i<right) 27 { 28 p[i]=min(p[2*id-i],right-i); 29 } 30 else 31 { 32 p[i]=1; 33 } 34 35 while(pre_s[i+p[i]]==pre_s[i-p[i]]) 36 { 37 p[i]++; 38 } 39 40 if(right<p[i]+i) 41 { 42 right=p[i]+i; 43 id=i; 44 } 45 } 46 47 int index=0; 48 int maxLen=0; 49 for(i=0;i<n1-1;i++) 50 { 51 if(p[i]>maxLen) 52 { 53 maxLen=p[i]-1; 54 index=i; 55 } 56 } 57 //注意此处找到原来串的位置 58 return s.substr((index-maxLen-1)/2,(maxLen)); 59 60 } 61 };