This problem have a long story. There is just too many solutions on the web and it is can studied for a long time before you fully grasp it. Morever, it can induce many other concepts or problems (longest palindromic subsequence, longest common substring, etc).
The simplest-solve it is-to-use two-dimensional DP. We denote p[i][j] to being an indicator of whether the substring from i to J (inclusive) is a Pali Ndrome. It is obvious that the following relationships hold:
- P[i][i] = 1 (Each character itself is palindromic);
- p[i][i + 1] = s[i] = = S[j] (Neighboring characters is palindromic if they is the same);
- P[i][j] = p[i + 1][j-1] && s[i] = = S[j] (If the substring is palindrome, then adding the same character at both of it, ends still gives a palindrome).
1 and 2 are base cases and 3 is the general case.
Then we'll have the following unoptimiezd DP code.
1 stringLongestpalindrome (strings) {2 intStart =0, Len =1, n =s.length ();3 BOOLdp[ +][ +] = {false};4 for(inti =0; I < n; i++)5Dp[i][i] =true;6 for(inti =0; I < n-1; i++) {7Dp[i][i +1] = s[i] = = S[i +1];8 if(Dp[i][i +1]) {9Start =i;TenLen =2; One } A } - for(intL =3; L <= N; l++) { - for(inti =0; I < N-l +1; i++) { the intj = i + L-1; -DP[I][J] = dp[i +1][j-1] && s[i] = =S[j]; - if(Dp[i][j]) { -Start =i; +Len =l; - } + } A } at returns.substr (start, Len); -}
Note that each time if we update dp[i][j], we only need Dp[i + 1][j-1] from the left column, so we C An maintain a, variable for it, and reduce the space complexity from O (n^2) to O (n). The code now becomes as follows.
1 stringLongestpalindrome (strings) {2 intStart =0, Len =1, n =s.length ();3 BOOLcur[ +] = {false};4 BOOLPre;5cur[0] =true;6 for(intj =1; J < N; J + +) {7CUR[J] =true;8Pre = Cur[j-1];9Cur[j-1] = s[j-1] ==S[j];Ten if(Cur[j-1] && Len <2) { OneStart = J-1; ALen =2; - } - for(inti = J-2; I >=0; i--) { the BOOLtemp =Cur[i]; -Cur[i] = Pre && s[i] = =S[j]; - if(Cur[i] && j-i +1>Len) { -Start =i; +Len = j-i +1; - } +Pre =temp; A } at } - returns.substr (start, Len); -}
We may also traverse the string and expand to left and right from any character to obtain the longest palindrome. The following code should is self-explanatory.
1 stringSearchstringSintLeftintRight ) {2 intL = left, r =Right ;3 while(L >=0&& R < s.length () && s[l] = =S[r]) {4l--;5r++;6 }7 returnS.SUBSTR (L +1, R-l-1);8 }9 Ten stringLongestpalindrome (strings) { One stringLongest = S.substr (0,1); A for(inti =0; I < s.length ()-1; i++) { - stringTMP1 =search (s, I, I); - stringTMP2 = Search (s, I, i +1); the if(Tmp1.length () > Longest.length ()) longest =Tmp1; - if(Tmp2.length () > Longest.length ()) longest =TMP2; - } - returnlongest; +}
Of course, this problem still have a non-trivial O (n) algorithm, named Manacher ' s algorithm. This page is a nice explanation for it. The final code is shown below.
1 stringProcessstrings) {2 intn =s.length ();3 stringT2* n +3,'#');4t[0] ='$';5t[2* n +2] ='%';6 for(inti =0; I < n; i++)7t[2* (i +1)] =S[i];8 returnT;9 }Ten One stringLongestpalindrome (strings) { A stringt =process (s); - intn =t.length (); - int* Plen =New int[n] (); the intCenter =0, right =0; - for(inti =1; I < n-1; i++) { - intI_mirror =2* Center-i; -Plen[i] = right > I? Min (Plen[i_mirror], right-i):0; + while(T[i + plen[i] +1] = = T[i-plen[i]-1]) -plen[i]++; + if(i + plen[i] >Right ) { ACenter =i; atright = i +Plen[i]; - } - } - intMaxLen =0; - for(inti =1; I < n-1; i++) { - if(Plen[i] >maxlen) { inCenter =i; -MaxLen =Plen[i]; to } + } - Delete[] Plen; the returnS.SUBSTR (center-1-MaxLen)/2, maxlen); *}
[Leetcode] Longest palindromic Substring