Facebook Pixel

3504. Longest Palindrome After Substring Concatenation II

Problem Description

You are given two strings s and t.

You need to find the longest possible palindrome that can be created by:

  1. Selecting a substring from s (which can be empty)
  2. Selecting a substring from t (which can be empty)
  3. Concatenating them in that order (substring from s followed by substring from t)

The task is to return the length of the longest palindrome that can be formed this way.

For example, if you have strings s and t, you could:

  • Use only a palindromic substring from s (leaving t's contribution empty)
  • Use only a palindromic substring from t (leaving s's contribution empty)
  • Use a substring from s concatenated with a substring from t that together form a palindrome

The key insight is that when concatenating substrings from both strings to form a palindrome, the ending portion of the substring from s must match (in reverse) with the beginning portion of the substring from t. This creates a palindromic structure where the first part mirrors the second part.

The solution approach involves:

  • Preprocessing both strings to find all palindromic substrings starting at each position
  • Using dynamic programming to find matching sequences between s and the reverse of t
  • Considering cases where additional palindromic content exists in either string beyond the matching portion
  • Tracking the maximum palindrome length across all possible combinations
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

To understand how to build the longest palindrome from two strings, let's think about what palindromes look like when formed from concatenated substrings.

A palindrome reads the same forwards and backwards. When we concatenate a substring from s with a substring from t, we get three possible scenarios:

  1. The palindrome comes entirely from one string: We simply need to find the longest palindromic substring in either s or t.

  2. The palindrome spans both strings: This is the interesting case. For the concatenated result to be a palindrome, the end of the substring from s must mirror the beginning of the substring from t.

Think of it this way: if we have "abc" from s and "cba" from t, concatenating gives us "abccba" - a palindrome! The key observation is that the substring from t needs to be the reverse of the substring from s for the concatenation to form a palindrome.

This leads us to reverse string t first. Now, finding matching parts between s and reversed t becomes a problem of finding common substrings, which we can solve with dynamic programming. When s[i] == reversed_t[j], we can extend our palindrome.

But there's another layer: what if after matching some characters between s and reversed t, there's still a palindromic tail in s or a palindromic head in reversed t? For example, if we match "ab" from s with "ba" from reversed t to get "abba", but s actually has "abcbc" where "cbc" is also a palindrome, we can include it to get "abcbcba"!

This is why we precompute g1[i] and g2[j] - they tell us the longest palindrome starting at position i in s and position j in reversed t respectively. After finding matching portions with DP, we check if we can extend the palindrome further using these precomputed values.

The formula f[i][j] * 2 + g1[i] represents: the matched portion doubled (since it appears in both halves of the palindrome) plus any additional palindromic content that can be added from the middle outward.

Learn more about Two Pointers and Dynamic Programming patterns.

Solution Approach

The implementation consists of three main components: preprocessing palindromes, reversing string t, and dynamic programming to find the longest palindrome.

Step 1: Preprocessing Palindromic Substrings

The calc function finds the longest palindromic substring starting at each position. It uses the expand helper function to check palindromes by expanding from centers:

  • For each position i, we try two types of centers:
    • Odd-length palindromes: expand from (i, i)
    • Even-length palindromes: expand from (i, i+1)
  • The expand function updates g[l] with the maximum palindrome length starting at position l
def expand(s: str, g: List[int], l: int, r: int):
    while l >= 0 and r < len(s) and s[l] == s[r]:
        g[l] = max(g[l], r - l + 1)
        l, r = l - 1, r + 1

Step 2: Reverse String t and Initialize

We reverse string t because we need to find matching sequences between the end of substring from s and the beginning of substring from t:

t = t[::-1]
g1, g2 = calc(s), calc(t)
ans = max(*g1, *g2)  # Initialize with longest palindrome from single string

Step 3: Dynamic Programming for Matching Sequences

We create a 2D DP table f[i][j] where f[i][j] represents the length of matching sequence ending at position i-1 in s and position j-1 in reversed t:

f = [[0] * (n + 1) for _ in range(m + 1)]
for i, a in enumerate(s, 1):
    for j, b in enumerate(t, 1):
        if a == b:
            f[i][j] = f[i - 1][j - 1] + 1

When characters match (a == b), we extend the matching sequence by 1.

Step 4: Calculate Maximum Palindrome Length

For each matching position, we consider two cases for extending the palindrome:

  1. Extend with remaining palindrome from s:

    ans = max(ans, f[i][j] * 2 + (0 if i >= m else g1[i]))
    • f[i][j] * 2: The matched portion appears twice (once from s, once from reversed t)
    • g1[i]: Additional palindrome starting from position i in s (if not at end)
  2. Extend with remaining palindrome from reversed t:

    ans = max(ans, f[i][j] * 2 + (0 if j >= n else g2[j]))
    • Similar logic but using g2[j] for the palindrome in reversed t

The final answer is the maximum palindrome length found across all possibilities.

Time Complexity: O(m*n) where m and n are lengths of strings s and t Space Complexity: O(m*n) for the DP table

Ready to land your dream job?

Unlock your dream job with a 3-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through the solution with s = "abcd" and t = "dcba".

Step 1: Preprocess palindromic substrings

For s = "abcd":

  • Position 0 ('a'): longest palindrome starting here = 1 ("a")
  • Position 1 ('b'): longest palindrome starting here = 1 ("b")
  • Position 2 ('c'): longest palindrome starting here = 1 ("c")
  • Position 3 ('d'): longest palindrome starting here = 1 ("d") So g1 = [1, 1, 1, 1]

For t = "dcba":

  • Position 0 ('d'): longest palindrome starting here = 1 ("d")
  • Position 1 ('c'): longest palindrome starting here = 1 ("c")
  • Position 2 ('b'): longest palindrome starting here = 1 ("b")
  • Position 3 ('a'): longest palindrome starting here = 1 ("a") So g2_original = [1, 1, 1, 1]

Step 2: Reverse string t

After reversing: t = "abcd" (reversed from "dcba") Now g2 = [1, 1, 1, 1] (positions correspond to reversed string)

Initialize ans = 1 (maximum from single character palindromes)

Step 3: Build DP table for matching sequences

We build f[i][j] where f[i][j] represents length of matching sequence ending at s[i-1] and t[j-1]:

    ""  a  b  c  d  (reversed t)
""  0   0  0  0  0
a   0   1  0  0  0
b   0   0  2  0  0  
c   0   0  0  3  0
d   0   0  0  0  4
(s)

Key matches:

  • f[1][1] = 1: "a" matches "a"
  • f[2][2] = 2: "ab" matches "ab"
  • f[3][3] = 3: "abc" matches "abc"
  • f[4][4] = 4: "abcd" matches "abcd"

Step 4: Calculate maximum palindrome

For each non-zero f[i][j], we check:

At f[1][1] = 1 (matched "a" from s and "a" from reversed t):

  • Case 1: 1 * 2 + g1[1] = 2 + 1 = 3 (palindrome: "aba")
  • Case 2: 1 * 2 + g2[1] = 2 + 1 = 3 (palindrome: "aba")
  • Update ans = 3

At f[2][2] = 2 (matched "ab" from s and "ab" from reversed t):

  • Case 1: 2 * 2 + g1[2] = 4 + 1 = 5 (palindrome: "abcba")
  • Case 2: 2 * 2 + g2[2] = 4 + 1 = 5 (palindrome: "abcba")
  • Update ans = 5

At f[3][3] = 3 (matched "abc" from s and "abc" from reversed t):

  • Case 1: 3 * 2 + g1[3] = 6 + 1 = 7 (palindrome: "abcdcba")
  • Case 2: 3 * 2 + g2[3] = 6 + 1 = 7 (palindrome: "abcdcba")
  • Update ans = 7

At f[4][4] = 4 (matched "abcd" from s and "abcd" from reversed t):

  • Case 1: 4 * 2 + 0 = 8 (i >= m, so no more characters in s)
  • Case 2: 4 * 2 + 0 = 8 (j >= n, so no more characters in reversed t)
  • Update ans = 8

Final Result: 8

The longest palindrome is "abcddcba" formed by taking "abcd" from s and "dcba" from t.

Solution Implementation

1class Solution:
2    def longestPalindrome(self, s: str, t: str) -> int:
3        """
4        Find the longest palindrome that can be formed by concatenating parts of strings s and t.
5        The palindrome can be formed by:
6        1. A palindrome from s alone
7        2. A palindrome from t alone  
8        3. A prefix from s + suffix from reversed t (forming a palindrome)
9        """
10      
11        def expand_around_center(string: str, palindrome_lengths: List[int], left: int, right: int) -> None:
12            """
13            Expand around center to find palindromes and update the maximum palindrome length
14            starting at each position.
15          
16            Args:
17                string: The input string
18                palindrome_lengths: Array storing max palindrome length starting at each index
19                left: Left pointer for expansion
20                right: Right pointer for expansion
21            """
22            while left >= 0 and right < len(string) and string[left] == string[right]:
23                # Update the maximum palindrome length starting at position 'left'
24                palindrome_lengths[left] = max(palindrome_lengths[left], right - left + 1)
25                left -= 1
26                right += 1
27      
28        def calculate_palindrome_lengths(string: str) -> List[int]:
29            """
30            Calculate the maximum palindrome length starting at each position in the string.
31          
32            Args:
33                string: Input string
34          
35            Returns:
36                List where palindrome_lengths[i] = max palindrome length starting at index i
37            """
38            n = len(string)
39            palindrome_lengths = [0] * n
40          
41            for i in range(n):
42                # Check for odd-length palindromes (single character center)
43                expand_around_center(string, palindrome_lengths, i, i)
44                # Check for even-length palindromes (two character center)
45                expand_around_center(string, palindrome_lengths, i, i + 1)
46          
47            return palindrome_lengths
48      
49        # Get lengths of input strings
50        m, n = len(s), len(t)
51      
52        # Reverse string t for easier computation
53        t_reversed = t[::-1]
54      
55        # Calculate max palindrome lengths starting at each position
56        palindrome_lengths_s = calculate_palindrome_lengths(s)
57        palindrome_lengths_t_reversed = calculate_palindrome_lengths(t_reversed)
58      
59        # Initialize answer with the longest palindrome from either string alone
60        max_palindrome_length = max(*palindrome_lengths_s, *palindrome_lengths_t_reversed)
61      
62        # dp[i][j] represents the length of longest common prefix between s[0:i] and t_reversed[0:j]
63        # This helps find matching prefixes and suffixes that can form palindromes
64        dp = [[0] * (n + 1) for _ in range(m + 1)]
65      
66        # Fill the DP table
67        for i, char_s in enumerate(s, 1):
68            for j, char_t_reversed in enumerate(t_reversed, 1):
69                if char_s == char_t_reversed:
70                    # Extend the common prefix length
71                    dp[i][j] = dp[i - 1][j - 1] + 1
72                  
73                    # Try forming palindrome: prefix from s + suffix from t + remaining palindrome from s
74                    if i < m:  # Check if there are remaining characters in s
75                        candidate_length = dp[i][j] * 2 + palindrome_lengths_s[i]
76                        max_palindrome_length = max(max_palindrome_length, candidate_length)
77                    else:
78                        # No remaining characters, just the matched prefix and suffix
79                        max_palindrome_length = max(max_palindrome_length, dp[i][j] * 2)
80                  
81                    # Try forming palindrome: prefix from s + suffix from t + remaining palindrome from t_reversed
82                    if j < n:  # Check if there are remaining characters in t_reversed
83                        candidate_length = dp[i][j] * 2 + palindrome_lengths_t_reversed[j]
84                        max_palindrome_length = max(max_palindrome_length, candidate_length)
85                    else:
86                        # No remaining characters, just the matched prefix and suffix
87                        max_palindrome_length = max(max_palindrome_length, dp[i][j] * 2)
88      
89        return max_palindrome_length
90
1class Solution {
2    /**
3     * Finds the longest palindrome that can be formed by concatenating a prefix of string S
4     * with a suffix of string T.
5     * 
6     * @param S first string
7     * @param T second string
8     * @return length of the longest palindrome
9     */
10    public int longestPalindrome(String S, String T) {
11        // Convert strings to character arrays for easier manipulation
12        char[] sArray = S.toCharArray();
13        // Reverse T to convert suffix matching to prefix matching
14        char[] tArrayReversed = new StringBuilder(T).reverse().toString().toCharArray();
15      
16        int sLength = sArray.length;
17        int tLength = tArrayReversed.length;
18      
19        // Calculate the longest palindrome starting at each position for both strings
20        int[] palindromeLengthsFromS = calculatePalindromeLengths(sArray);
21        int[] palindromeLengthsFromT = calculatePalindromeLengths(tArrayReversed);
22      
23        // Initialize answer with the longest palindrome from either string alone
24        int maxPalindromeLength = Math.max(
25            Arrays.stream(palindromeLengthsFromS).max().getAsInt(),
26            Arrays.stream(palindromeLengthsFromT).max().getAsInt()
27        );
28      
29        // DP table where dp[i][j] represents the length of common prefix
30        // between sArray[0...i-1] and tArrayReversed[0...j-1]
31        int[][] dp = new int[sLength + 1][tLength + 1];
32      
33        // Fill the DP table
34        for (int i = 1; i <= sLength; ++i) {
35            for (int j = 1; j <= tLength; ++j) {
36                // If characters match, extend the common prefix
37                if (sArray[i - 1] == tArrayReversed[j - 1]) {
38                    dp[i][j] = dp[i - 1][j - 1] + 1;
39                  
40                    // Case 1: Use prefix from S + suffix from T + remaining palindrome from S
41                    // The total length is: common prefix/suffix * 2 + palindrome starting after prefix in S
42                    if (i < sLength) {
43                        maxPalindromeLength = Math.max(maxPalindromeLength, 
44                            dp[i][j] * 2 + palindromeLengthsFromS[i]);
45                    }
46                  
47                    // Case 2: Use prefix from S + suffix from T + remaining palindrome from T
48                    // The total length is: common prefix/suffix * 2 + palindrome starting after prefix in T
49                    if (j < tLength) {
50                        maxPalindromeLength = Math.max(maxPalindromeLength, 
51                            dp[i][j] * 2 + palindromeLengthsFromT[j]);
52                    }
53                }
54            }
55        }
56      
57        return maxPalindromeLength;
58    }
59
60    /**
61     * Expands around the given center to find palindromes and updates the maximum
62     * palindrome length starting at each position.
63     * 
64     * @param charArray the character array to search in
65     * @param palindromeLengths array to store maximum palindrome lengths
66     * @param left starting left index of expansion
67     * @param right starting right index of expansion
68     */
69    private void expand(char[] charArray, int[] palindromeLengths, int left, int right) {
70        // Expand while characters match and indices are valid
71        while (left >= 0 && right < charArray.length && charArray[left] == charArray[right]) {
72            // Update the maximum palindrome length starting at position 'left'
73            palindromeLengths[left] = Math.max(palindromeLengths[left], right - left + 1);
74            --left;
75            ++right;
76        }
77    }
78
79    /**
80     * Calculates the maximum palindrome length starting at each position in the array.
81     * 
82     * @param charArray the character array to analyze
83     * @return array where index i contains the length of longest palindrome starting at position i
84     */
85    private int[] calculatePalindromeLengths(char[] charArray) {
86        int length = charArray.length;
87        int[] palindromeLengths = new int[length];
88      
89        // For each position, check for palindromes with both odd and even lengths
90        for (int i = 0; i < length; ++i) {
91            // Check for odd-length palindromes (single character center)
92            expand(charArray, palindromeLengths, i, i);
93            // Check for even-length palindromes (two character center)
94            expand(charArray, palindromeLengths, i, i + 1);
95        }
96      
97        return palindromeLengths;
98    }
99}
100
1class Solution {
2public:
3    int longestPalindrome(string s, string t) {
4        int m = s.size(), n = t.size();
5      
6        // Reverse string t to find common substrings between s and reverse of t
7        ranges::reverse(t);
8      
9        // Calculate the longest palindrome starting at each position for both strings
10        vector<int> longestPalindromeFromS = calculateLongestPalindromeFrom(s);
11        vector<int> longestPalindromeFromT = calculateLongestPalindromeFrom(t);
12      
13        // Initialize answer with the longest palindrome in either string alone
14        int maxLength = max(ranges::max(longestPalindromeFromS), 
15                           ranges::max(longestPalindromeFromT));
16      
17        // dp[i][j] represents the length of longest common suffix between s[0..i-1] and t[0..j-1]
18        vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
19      
20        // Build DP table to find longest common substrings
21        for (int i = 1; i <= m; ++i) {
22            for (int j = 1; j <= n; ++j) {
23                if (s[i - 1] == t[j - 1]) {
24                    // Extend the common substring
25                    dp[i][j] = dp[i - 1][j - 1] + 1;
26                  
27                    // Try to form palindrome: common_substring + palindrome_from_s
28                    // The common substring contributes twice (original + reversed)
29                    if (i < m) {
30                        maxLength = max(maxLength, dp[i][j] * 2 + longestPalindromeFromS[i]);
31                    }
32                  
33                    // Try to form palindrome: common_substring + palindrome_from_t
34                    if (j < n) {
35                        maxLength = max(maxLength, dp[i][j] * 2 + longestPalindromeFromT[j]);
36                    }
37                }
38            }
39        }
40      
41        return maxLength;
42    }
43
44private:
45    // Expand around center to find palindrome and update the longest palindrome starting at each position
46    void expandAroundCenter(const string& s, vector<int>& longestFrom, int left, int right) {
47        while (left >= 0 && right < s.size() && s[left] == s[right]) {
48            // Update the longest palindrome starting at position 'left'
49            longestFrom[left] = max(longestFrom[left], right - left + 1);
50            --left;
51            ++right;
52        }
53    }
54
55    // Calculate the longest palindrome starting at each position in the string
56    vector<int> calculateLongestPalindromeFrom(const string& s) {
57        int n = s.size();
58        vector<int> longestFrom(n, 0);
59      
60        for (int i = 0; i < n; ++i) {
61            // Check for odd-length palindromes (single character center)
62            expandAroundCenter(s, longestFrom, i, i);
63            // Check for even-length palindromes (two character center)
64            expandAroundCenter(s, longestFrom, i, i + 1);
65        }
66      
67        return longestFrom;
68    }
69};
70
1/**
2 * Finds the longest palindrome that can be formed by concatenating a prefix of string s
3 * with a suffix of string t (or vice versa), or just using a substring from either string.
4 */
5function longestPalindrome(s: string, t: string): number {
6    /**
7     * Expands around center to find palindromes and updates the maximum palindrome length
8     * starting at each position in the array.
9     * @param str - The string to search for palindromes
10     * @param maxLengths - Array storing max palindrome length starting at each index
11     * @param left - Left pointer for expansion
12     * @param right - Right pointer for expansion
13     */
14    function expandAroundCenter(
15        str: string, 
16        maxLengths: number[], 
17        left: number, 
18        right: number
19    ): void {
20        // Expand while characters match and we're within bounds
21        while (left >= 0 && right < str.length && str[left] === str[right]) {
22            // Update max palindrome length starting at position 'left'
23            maxLengths[left] = Math.max(maxLengths[left], right - left + 1);
24            left--;
25            right++;
26        }
27    }
28
29    /**
30     * Calculates the maximum palindrome length starting at each position in the string.
31     * @param str - The input string
32     * @returns Array where each index contains the max palindrome length starting at that position
33     */
34    function calculatePalindromeLengths(str: string): number[] {
35        const length = str.length;
36        const maxPalindromeLengths: number[] = Array(length).fill(0);
37      
38        for (let i = 0; i < length; i++) {
39            // Check for odd-length palindromes (single character center)
40            expandAroundCenter(str, maxPalindromeLengths, i, i);
41            // Check for even-length palindromes (two character center)
42            expandAroundCenter(str, maxPalindromeLengths, i, i + 1);
43        }
44      
45        return maxPalindromeLengths;
46    }
47
48    const sLength = s.length;
49    const tLength = t.length;
50  
51    // Reverse string t for suffix-prefix matching
52    const reversedT = t.split('').reverse().join('');
53  
54    // Calculate max palindrome lengths for both strings
55    const palindromeLengthsS = calculatePalindromeLengths(s);
56    const palindromeLengthsT = calculatePalindromeLengths(reversedT);
57  
58    // Initialize answer with the longest palindrome from either string alone
59    let maxPalindromeLength = Math.max(...palindromeLengthsS, ...palindromeLengthsT);
60
61    // DP table for longest common prefix between s and reversed t
62    // dp[i][j] represents the longest common substring ending at s[i-1] and reversedT[j-1]
63    const dp: number[][] = Array.from(
64        { length: sLength + 1 }, 
65        () => Array(tLength + 1).fill(0)
66    );
67
68    // Fill DP table to find matching prefixes and suffixes
69    for (let i = 1; i <= sLength; i++) {
70        for (let j = 1; j <= tLength; j++) {
71            if (s[i - 1] === reversedT[j - 1]) {
72                // Extend the common substring length
73                dp[i][j] = dp[i - 1][j - 1] + 1;
74              
75                // Check palindrome formed by: prefix from s + suffix from t + remaining palindrome in s
76                if (i < sLength) {
77                    maxPalindromeLength = Math.max(
78                        maxPalindromeLength, 
79                        dp[i][j] * 2 + palindromeLengthsS[i]
80                    );
81                }
82              
83                // Check palindrome formed by: prefix from s + suffix from t + remaining palindrome in t
84                if (j < tLength) {
85                    maxPalindromeLength = Math.max(
86                        maxPalindromeLength, 
87                        dp[i][j] * 2 + palindromeLengthsT[j]
88                    );
89                }
90            }
91        }
92    }
93
94    return maxPalindromeLength;
95}
96

Time and Space Complexity

The time complexity of this code is O(m² + n² + m × n), where m is the length of string s and n is the length of string t.

Breaking down the time complexity:

  • The calc function is called twice - once for string s and once for reversed string t
  • For calc(s): The function iterates through each position in the string (O(m) iterations), and for each position, calls expand twice. The expand function can potentially check up to O(m) characters in the worst case (expanding from center to edges). This gives O(m²) for processing string s
  • For calc(t): Similarly, this takes O(n²) for processing reversed string t
  • The nested loops for dynamic programming iterate m × n times, with O(1) operations in each iteration, contributing O(m × n)
  • Total: O(m² + n² + m × n)

However, the reference answer states O(m × (m + n)). This appears to be a simplification or different interpretation. If we consider that typically m and n are of similar magnitude, or if m ≥ n, then O(m² + n² + m × n) could be bounded by O(m × (m + n)).

The space complexity is O(m × n), where:

  • The 2D array f uses O((m + 1) × (n + 1)) = O(m × n) space
  • Arrays g1 and g2 use O(m) and O(n) space respectively
  • Total: O(m × n + m + n) = O(m × n) (since m × n dominates for non-trivial inputs)

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Incorrect Palindrome Extension Logic

Pitfall: A common mistake is incorrectly calculating the total palindrome length when combining matched sequences with remaining palindromes. Developers often forget that the matched portion contributes twice to the final length (once from s and once from reversed t).

Incorrect Implementation:

# Wrong: Only counting matched portion once
ans = max(ans, f[i][j] + g1[i])  # Missing multiplication by 2

Correct Implementation:

# Correct: Matched portion appears twice in the final palindrome
ans = max(ans, f[i][j] * 2 + (0 if i >= m else g1[i]))

2. Off-by-One Errors in DP Indexing

Pitfall: The DP table uses 1-indexed positions while the palindrome arrays use 0-indexed positions. This mismatch frequently causes index errors when accessing the palindrome length arrays.

Incorrect Implementation:

for i in range(1, m + 1):
    for j in range(1, n + 1):
        if s[i-1] == t_reversed[j-1]:
            f[i][j] = f[i-1][j-1] + 1
            # Wrong: Using 1-indexed i directly with 0-indexed g1
            ans = max(ans, f[i][j] * 2 + g1[i])  # IndexError when i == m

Correct Implementation:

for i, char_s in enumerate(s, 1):  # i is 1-indexed
    for j, char_t in enumerate(t_reversed, 1):  # j is 1-indexed
        if char_s == char_t:
            dp[i][j] = dp[i-1][j-1] + 1
            # Correct: Check bounds and use proper index
            if i < m:  # Ensure i is valid index for g1 (0-indexed)
                ans = max(ans, dp[i][j] * 2 + g1[i])

3. Forgetting to Consider Single-String Palindromes

Pitfall: Only focusing on concatenated palindromes and forgetting that the longest palindrome might come from just one string alone.

Incorrect Implementation:

ans = 0  # Wrong: Starting with 0 ignores single-string palindromes
# ... DP logic ...
return ans

Correct Implementation:

# Initialize with the longest palindrome from either string alone
ans = max(*g1, *g2)
# ... DP logic ...
return ans

4. Not Handling Edge Cases Properly

Pitfall: Failing to handle edge cases when one or both strings are empty, or when the matching sequence extends to the end of either string.

Solution: Always check boundaries before accessing array elements:

# Check if there are remaining characters before accessing palindrome arrays
if i < m:
    ans = max(ans, dp[i][j] * 2 + palindrome_lengths_s[i])
else:
    ans = max(ans, dp[i][j] * 2)  # No remaining characters to add

if j < n:
    ans = max(ans, dp[i][j] * 2 + palindrome_lengths_t_reversed[j])
else:
    ans = max(ans, dp[i][j] * 2)

5. Misunderstanding the Problem Requirements

Pitfall: Thinking that the entire strings must be used, or that the substrings must be contiguous in a specific way.

Key Understanding:

  • Substrings from s and t can be empty
  • The concatenation order matters (substring from s first, then from t)
  • The goal is to form a palindrome, which requires the end of the s substring to match (in reverse) with the beginning of the t substring

Implementation Tip: Reversing t at the beginning simplifies the matching logic, as you're now looking for common prefixes between s and reversed t.

Discover Your Strengths and Weaknesses: Take Our 3-Minute Quiz to Tailor Your Study Plan:

Consider the classic dynamic programming of longest increasing subsequence:

Find the length of the longest subsequence of a given sequence such that all elements of the subsequence are sorted in increasing order.

For example, the length of LIS for [50, 3, 10, 7, 40, 80] is 4 and LIS is [3, 7, 40, 80].

What is the recurrence relation?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More