Welcome to Subscribe On Youtube

5. Longest Palindromic Substring

Description

Given a string s, return the longest palindromic substring in s.

 

Example 1:

Input: s = "babad"
Output: "bab"
Explanation: "aba" is also a valid answer.

Example 2:

Input: s = "cbbd"
Output: "bb"

 

Constraints:

  • 1 <= s.length <= 1000
  • s consist of only digits and English letters.

Solutions

Solution 1: Dynamic Programming

We define $f[i][j]$ to represent whether the string $s[i..j]$ is a palindrome, initially $f[i][j] = true$.

Next, we define variables $k$ and $mx$, where $k$ represents the starting position of the longest palindrome, and $mx$ represents the length of the longest palindrome. Initially, $k = 0$, $mx = 1$.

Considering $f[i][j]$, if $s[i] = s[j]$, then $f[i][j] = f[i + 1][j - 1]$; otherwise, $f[i][j] = false$. If $f[i][j] = true$ and $mx < j - i + 1$, then we update $k = i$, $mx = j - i + 1$.

Since $f[i][j]$ depends on $f[i + 1][j - 1]$, we need to ensure that $i + 1$ is before $j - 1$, so we need to enumerate $i$ from large to small, and enumerate $j$ from small to large.

The time complexity is $O(n^2)$, and the space complexity is $O(n^2)$. Here, $n$ is the length of the string $s$.

Solution 2: Enumerate Palindrome Midpoint

We can enumerate the midpoint of the palindrome, spread to both sides, and find the longest palindrome.

The time complexity is $O(n^2)$, and the space complexity is $O(1)$. Here, $n$ is the length of the string $s$.

  • class Solution {
        public String longestPalindrome(String s) {
            int n = s.length();
            boolean[][] f = new boolean[n][n];
            for (var g : f) {
                Arrays.fill(g, true);
            }
            int k = 0, mx = 1;
            for (int i = n - 2; i >= 0; --i) {
                for (int j = i + 1; j < n; ++j) {
                    f[i][j] = false;
                    if (s.charAt(i) == s.charAt(j)) {
                        f[i][j] = f[i + 1][j - 1];
                        if (f[i][j] && mx < j - i + 1) {
                            mx = j - i + 1;
                            k = i;
                        }
                    }
                }
            }
            return s.substring(k, k + mx);
        }
    }
    
  • class Solution {
    public:
        string longestPalindrome(string s) {
            int n = s.size();
            vector<vector<bool>> f(n, vector<bool>(n, true));
            int k = 0, mx = 1;
            for (int i = n - 2; ~i; --i) {
                for (int j = i + 1; j < n; ++j) {
                    f[i][j] = false;
                    if (s[i] == s[j]) {
                        f[i][j] = f[i + 1][j - 1];
                        if (f[i][j] && mx < j - i + 1) {
                            mx = j - i + 1;
                            k = i;
                        }
                    }
                }
            }
            return s.substr(k, mx);
        }
    };
    
  • class Solution:
        def longestPalindrome(self, s: str) -> str:
            mlen = 0
            start = end = 0
            n = len(s)
            dp = [ [False] * n for i in range(n) ]
    
            for j in range(n):
                for i in range(j + 1):
                    dp[i][j] = (i == j) or (s[i] == s[j] and j - i == 1) or (s[i] == s[j] and dp[i + 1][j - 1])
                    if dp[i][j] is True and j - i + 1 > mlen:
                        mlen = j - i + 1
                        start = i
                        end = j
    
            return s[start: end + 1]
    
    ######
    
    class Solution:
        def longestPalindrome(self, s: str) -> str:
            n = len(s)
            f = [[True] * n for _ in range(n)]
            k, mx = 0, 1
            for i in range(n - 2, -1, -1):
                for j in range(i + 1, n):
                    f[i][j] = False
                    if s[i] == s[j]:
                        f[i][j] = f[i + 1][j - 1]
                        if f[i][j] and mx < j - i + 1:
                            k, mx = i, j - i + 1
            return s[k : k + mx]
    
    
  • func longestPalindrome(s string) string {
    	n := len(s)
    	f := make([][]bool, n)
    	for i := range f {
    		f[i] = make([]bool, n)
    		for j := range f[i] {
    			f[i][j] = true
    		}
    	}
    	k, mx := 0, 1
    	for i := n - 2; i >= 0; i-- {
    		for j := i + 1; j < n; j++ {
    			f[i][j] = false
    			if s[i] == s[j] {
    				f[i][j] = f[i+1][j-1]
    				if f[i][j] && mx < j-i+1 {
    					mx = j - i + 1
    					k = i
    				}
    			}
    		}
    	}
    	return s[k : k+mx]
    }
    
  • function longestPalindrome(s: string): string {
        const n = s.length;
        const f: boolean[][] = Array(n)
            .fill(0)
            .map(() => Array(n).fill(true));
        let k = 0;
        let mx = 1;
        for (let i = n - 2; i >= 0; --i) {
            for (let j = i + 1; j < n; ++j) {
                f[i][j] = false;
                if (s[i] === s[j]) {
                    f[i][j] = f[i + 1][j - 1];
                    if (f[i][j] && mx < j - i + 1) {
                        mx = j - i + 1;
                        k = i;
                    }
                }
            }
        }
        return s.slice(k, k + mx);
    }
    
    
  • /**
     * @param {string} s
     * @return {string}
     */
    var longestPalindrome = function (s) {
        const n = s.length;
        const f = Array(n)
            .fill(0)
            .map(() => Array(n).fill(true));
        let k = 0;
        let mx = 1;
        for (let i = n - 2; i >= 0; --i) {
            for (let j = i + 1; j < n; ++j) {
                f[i][j] = false;
                if (s[i] === s[j]) {
                    f[i][j] = f[i + 1][j - 1];
                    if (f[i][j] && mx < j - i + 1) {
                        mx = j - i + 1;
                        k = i;
                    }
                }
            }
        }
        return s.slice(k, k + mx);
    };
    
    
  • public class Solution {
        public string LongestPalindrome(string s) {
            int n = s.Length;
            bool[,] f = new bool[n, n];
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; ++j) {
                    f[i, j] = true;
                }
            }
            int k = 0, mx = 1;
            for (int i = n - 2; i >= 0; --i) {
                for (int j = i + 1; j < n; ++j) {
                    f[i, j] = false;
                    if (s[i] == s[j]) {
                        f[i, j] = f[i + 1, j - 1];
                        if (f[i, j] && mx < j - i + 1) {
                            mx = j - i + 1;
                            k = i;
                        }
                    }
                }
            }
            return s.Substring(k, mx);
        }
    }
    
  • import std/sequtils
    
    proc longestPalindrome(s: string): string =
      let n: int = s.len()
      var
        dp = newSeqWith[bool](n, newSeqWith[bool](n, false))
        start: int = 0
        mx: int = 1
    
      for j in 0 ..< n:
        for i in 0 .. j:
          if j - i < 2:
            dp[i][j] = s[i] == s[j]
          else:
            dp[i][j] = dp[i + 1][j - 1] and s[i] == s[j]
    
          if dp[i][j] and mx < j - i + 1:
            start = i
            mx = j - i + 1
    
      result = s[start ..< start+mx]
    
    # Driver Code
    # echo(longestPalindrome("adbdaba"))
    
    
  • impl Solution {
        pub fn longest_palindrome(s: String) -> String {
            let (n, mut ans) = (s.len(), &s[..1]);
            let mut dp = vec![vec![false; n]; n];
            let data: Vec<char> = s.chars().collect();
    
            for end in 1..n {
                for start in 0..=end {
                    if data[start] == data[end] {
                        dp[start][end] = end - start < 2 || dp[start + 1][end - 1];
                        if dp[start][end] && end - start + 1 > ans.len() {
                            ans = &s[start..=end];
                        }
                    }
                }
            }
            ans.to_string()
        }
    }
    
    
  • class Solution {
        /**
         * @param string $s
         * @return string
         */
        function longestPalindrome($s) {
            $start = 0;
            $maxLength = 0;
    
            for ($i = 0; $i < strlen($s); $i++) {
                $len1 = $this->expandFromCenter($s, $i, $i);
                $len2 = $this->expandFromCenter($s, $i, $i + 1);
    
                $len = max($len1, $len2);
    
                if ($len > $maxLength) {
                    $start = $i - intval(($len - 1) / 2);
                    $maxLength = $len;
                }
            }
    
            return substr($s, $start, $maxLength);
        }
    
        function expandFromCenter($s, $left, $right) {
            while ($left >= 0 && $right < strlen($s) && $s[$left] === $s[$right]) {
                $left--;
                $right++;
            }
    
            return $right - $left - 1;
        }
    }
    
    

All Problems

All Solutions