Longest Palindromic Subsequence
Problem Statement
Given a string 'S', your objective is to identify the length of the longest palindromic subsequence. In simpler terms, you're tasked with finding the longest sequence of characters in 'S' that can be read the same forwards and backwards, but not necessarily in consecutive order.
Example
Approach-1: Using Recursive Solution
- Base case: If a single character is considered, it's always a palindrome of length 1.
- If the first and last characters are different: In this case, the length of the LPS is the maximum of either excluding the first character or excluding the last character.
- If there are only 2 characters and both are the same: In this scenario, the length of the LPS is 2.
- If the first and last characters are the same: Here, we add 2 to the length of the LPS of the substring excluding the first and last characters.
Dry Run:
Code Implementation
C++:
Java:
Python:
Output :
Complexity Analysis
- Time Complexity - Since we are recurring for each subsequence of string , the overall time complexity is equal to the number of possible subsequences which is nothing but .
- Space Complexity - Though we are not using any auxiliary data structure, due to multiple sub-problems the maximum height of the recursive stack can reach up to , hence overall space complexity is .
Approach-2: Memoization Technique
- Create a Memoization Table: Initialize a 2D memoization table dp of size n x n. Initialize all values in dp to -1 initially.
- Modify the Recursive Function: Modify the recursive function to check the memoization table before making recursive calls. If the value for the current indices (i, j) is already computed, return the stored value from the memoization table.
Code Implementation
C++:
Java:
Python:
Output:
Complexity Analysis
- Time Complexity - The time complexity of memoization code has now been reduced to from , due to which the problem becomes solvable as per the given constraints of the question.
- Space Complexity - As we are using an auxiliary 2-D array of dimension due to which the space complexity becomes .
Approach-3: Using the Tabulation Technique of Dynamic Programming
We will define our DP state dp[i][j] which denotes the length of the LPS of the string . Then we will see the state transitions -
Algorithm
Now we will use the gap strategy to fill the dp table step-by-step using the following logic. Let be the string of length , we will start filling the dp table for all substring with gap 0 then with gap 1, and so on till the gap of . Here means all substring with gap such that .
- Declare a 2-D array of size .
- Iterate for to and do the following -
- Declare a variable say and initialize it to 0.
- Iterate for to and do the following -
- Fill the dp[i][j] as per the state transitions described above.
- Increment i by 1, i++
- Now dp[0][n-1] will contain the length of the LPS for string original string. Hence, we will return it as the answer.
Code Implementation
C++:
Java:
Python:
Output:
Complexity Analysis
- Time Complexity - In the first iteration the inner loop runs for time, in the second iteration it runs for time, and similarly in the iteration inner loop runs for 1 time. Hence the total number of executions of the inner loop is which is an order of and hence the time complexity is .
- Space Complexity - We have used a 2-D array of dimension due to which the space complexity is .
Explore Scaler Topics Data Structures Tutorial and enhance your DSA skills with Reading Tracks and Challenges.
Conclusion
- Problem Definition: The Longest Palindromic Subsequence (LPS) problem involves finding the length of the longest subsequence in a given string that reads the same forwards and backwards.
- Naive Approach: A naive solution of longest palindromic subsequence problem involves generating all possible subsequences of the given string and checking each one for palindromic properties. However, this approach is exponential in time complexity.
- Dynamic Programming: By applying dynamic programming techniques to longest palindromic subsequence problem, it can be efficiently solved. This involves breaking down the problem into smaller subproblems and storing their solutions to avoid redundant computations.
- Memoization Technique: Memoization involves storing the results of previously computed subproblems to avoid recalculating them. This significantly reduces the time complexity by eliminating redundant recursive calls.
- Tabulation Technique: Another dynamic programming approach involves filling up a table iteratively, bottom-up, starting from smaller subproblems to larger ones. This method further enhances efficiency by eliminating recursion overhead of longest palindromic subsequence problem.
- Complexity Analysis: Both memoization and tabulation techniques achieve a time complexity of O(n^2) and a space complexity of O(n^2), making the problem solvable within reasonable time and space constraints for large inputs.