Longest repeating subsequence
Problem: Longest Repeating Subsequence
Statement
Given a string s, find the length of the longest subsequence that appears at least twice in the string without reusing the same index.
Intuition
We want to find the Longest Common Subsequence (LCS) of the string with itself, but with the restriction that the indices must not be the same.
Key Idea:
Use a variation of LCS with the condition:
If characters match, they should be at different indices (i != j).
Recursive Approach
class Solution {
int lrs(String s1, String s2, int i, int j) {
if (i == 0 || j == 0) return 0;
if (s1.charAt(i - 1) == s2.charAt(j - 1) && i != j) {
return 1 + lrs(s1, s2, i - 1, j - 1);
} else {
return Math.max(lrs(s1, s2, i - 1, j), lrs(s1, s2, i, j - 1));
}
}
int LongestRepeatingSubsequence(String s) {
int n = s.length();
return lrs(s, s, n, n);
}
}
Time Complexity:
O(2^n) — Exponential
Memoization (Top-down DP)
class Solution {
int[][] dp;
int lrs(String s1, String s2, int i, int j) {
if (i == 0 || j == 0) return 0;
if (dp[i][j] != -1) return dp[i][j];
if (s1.charAt(i - 1) == s2.charAt(j - 1) && i != j) {
return dp[i][j] = 1 + lrs(s1, s2, i - 1, j - 1);
} else {
return dp[i][j] = Math.max(lrs(s1, s2, i - 1, j), lrs(s1, s2, i, j - 1));
}
}
int LongestRepeatingSubsequence(String s) {
int n = s.length();
dp = new int[n + 1][n + 1];
for (int[] row : dp) Arrays.fill(row, -1);
return lrs(s, s, n, n);
}
}
Time Complexity: O(n^2)
Space Complexity: O(n^2)
Tabulation (Bottom-up DP)
class Solution {
int LongestRepeatingSubsequence(String s) {
int n = s.length();
int[][] dp = new int[n + 1][n + 1];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (s.charAt(i - 1) == s.charAt(j - 1) && i != j) {
dp[i][j] = 1 + dp[i - 1][j - 1];
} else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
return dp[n][n];
}
}
Time and Space Complexity
| Method | Time Complexity | Space Complexity |
|---|---|---|
| Recursion | O(2^n) | O(1) |
| Memoization | O(n^2) | O(n^2) |
| Tabulation | O(n^2) | O(n^2) |
Dry Run
Example: s = "aab"
Comparing "aab" with itself:
i != j is checked:
LRS = "a" → appears twice at different indices.
Length = 1
Summary
-
The problem is a twist on the classical LCS problem.
-
We solve it using LCS logic on the string with itself, skipping identical indices.
-
Best to use Tabulation in interviews for clarity and efficiency.