Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example 1:
Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.
Example 2:
Input: "cbbd"
Output: "bb"
class Solution {
public:
string stringReversal(string s){
string sr;
for(int i = s.length()-1,j=0; i >=0,j<s.length(); i--,j++)
{
sr.insert(j, {s.at(i)});
}
return sr;
}
string longestPalindrome(string s)
{
string the_string;
int max_palindromic_length = 0;
for(int i = 0; i < s.length(); i++)
{
for(int j = i; j<s.length(); j++)
{
string this_str;
for(int x = i,y=0; x<=j;x++,y++)
{
this_str.insert(y,{s.at(x)});
}
string sr = stringReversal(this_str);
if(sr == this_str){
if(j-i>=max_palindromic_length){
max_palindromic_length = j-i;
the_string = this_str;
}
}
}
}
return the_string;
}
};
comment:
The big-oh of Time-Complexity is too large that can't hit the calculating time requirement of leetcode when they input a very long string...
Solution 2: Longest common substring
code:
string longestPalindrome(string s)
{
if(s.length()==1) return s;
string rev = s;
std::reverse(rev.begin(), rev.end());
if(rev==s) return s;
string result;
int len = 0;
for(int i = 0; i<s.length(); i++)
{
string sub_string;
for(int j=i; j<s.length();j++)
{
sub_string = sub_string + s[j];
if(len>=sub_string.length()){
continue;
}else if(rev.find(sub_string)!=-1){
string check = sub_string;
std::reverse(check.begin(), check.end());
if(sub_string == check){
len = sub_string.length();
result =sub_string;
}
}else{
break;
}
}
}
return result;
}
comment:
It's still out of time when input is too long.
Solution2: Dynamic Programming
code:
string longestPalindrome(string s)
{
int len = s.size();
if(len==0||len==1){
return s;}
vector<vector<int>> dp(len, vector<int>(len));
int start = 0;
int max = 1;
for(int i = 0; i < len; i++)
{
dp[i][i] = 1;//if dp[x][y] is equal to 1, it's a palindromic string
if(i<len-1&&s[i]==s[i+1]) //a string of two consecutive identical letters is a palindromic string
{
dp[i][i+1] = 1;
start = i;
max = 2;
}
}
for (int l = 3; l<=len; l++)
{
for(int i = 0; i+l-1<len; i++)
{
int j = i+l-1;
if(s[i]==s[j]&&dp[i+1][j-1]==1) //if a string xyz is already a palindromic string, and let's say axyzb, if a ==b, axyzb is //palindromic string too
{
dp[i][j] = 1; //now,let axyzb be palindromic string
start = i;
max = l;
}
}
}
return s.substr(start, max);
}
comment:
256 ms | 186.5 MB | Cpp |
I think my notes are clear enuf...
Solution4: Expand Around Center
code:
class Solution {
public:
string longestPalindrome(string s)
{
int len = s.size();
if(len==0||len==1)
{
return s;
}
int mlen = 0;
int start = 0;
int end = 0;
for(int i = 0; i < len; i ++)
{
int len1 = sizeOfPalindromic(s, i, i);
int len2 = sizeOfPalindromic(s, i, i+1);
mlen=max(max(len1,len2),mlen);
if(mlen>end-start+1)
{
start = i-(mlen-1)/2;
end = i+mlen/2;
}
}
return s.substr(start, mlen); //from start, and mlen length of string
}
private:
int sizeOfPalindromic(string s, int left, int right)
{
int L=left;
int R=right;
while(L>=0&&R<s.size()&&s[L]==s[R])
{
L--;
R++;
}
return R-L-1; //this return the value of length of a palindromic string,
//it's kinda confusing, cuz the while loop expanded the length of it
//in a fact, R-L-1 is the real palindromic string
}
};
comment:
44 ms | 104.1 MB | Cpp |
Solution5: Manacher
code:
string longestPalindrome(string s)
{
if(s.length()<1){
return "";
}
string vs;
for (int i = 0; i <s.length(); i ++){
vs += "#";
vs += s[i];
}
vs += "#"; //we let string be #a#b#c#b#a#, to let the virtual string(vs) be an odd number of string // later we just divides it by 2 to get the original position
int len = vs.length();
int pos = 0; //the current pos of currentMaxRight
int currentMaxRight = 0; //as the name represents, if current palindromic string's right of loop beyond it, we update it.
int maxPos = 0; //to store the max radius of a pos
int maxRL = 0; // to strore the max radius
int * RL = new int[len]; //to store the current radius
for(int i = 0; i <len; i ++)
{
//we initialize the radius in one of 2 cases
if(i<currentMaxRight){ //case one: the i is on the left side of currentMaxRight.
//there is either j(j is a symmetric point with pos as axis i)'s left reaches the currentMaxLeft //or right reaches currentMaxRight
//and we pick the limited situation, hence we use min()
RL[i] = min(RL[2*pos-i],currentMaxRight-i);
}else //case two: i is on the right side of currentMaxRight, or just on currentMaxRight
{
RL[i] = 1; //included the i himself, hence later we gotta use RL[i]-1 to caculate the distance
}
//now we start to expand from current center
while((i-RL[i]>=0)&&(i+RL[i]<len)&&(vs[i+RL[i]]==vs[i-RL[i]])) //of course left or right can't beyond border
{
RL[i] +=1;
}
//if i+RL[i] is greater than currentMaxRight, update it to i+RL[i]
if(i+RL[i]-1>currentMaxRight)
{
currentMaxRight = i+RL[i]-1;
pos = i;
}
//if RL[i]>currentMaxRight-pos
if(RL[i]>=maxRL)
{
maxPos = i;
maxRL= RL[i];
}
}
return s.substr((maxPos-(maxRL-1))/2, maxRL - 1); //cuz of it's virtual string, hence divided by 2 //and we said distance is RL-1
}
comment:
8 ms | 9.9 MB | Cpp |
The main idea of this algorithm is to make use of the attribute of symmetry of a palindromic string to avoid repetitive operation, while does "Expand Around Center" at the same time.
I think my notes are clear enuf...