|
| 1 | +--- |
| 2 | +id: longest-subsequence-repeated-k-times |
| 3 | +title: Longest Subsequence Repeated k Times |
| 4 | +sidebar_label: 2014. Longest Subsequence Repeated k Times |
| 5 | + |
| 6 | +tags: |
| 7 | +- String |
| 8 | +- Backtracking |
| 9 | +- Greedy |
| 10 | +- Counting |
| 11 | +- Enumeration |
| 12 | + |
| 13 | +description: "This is a solution to the Longest Subsequence Repeated k Times problem on LeetCode." |
| 14 | +--- |
| 15 | + |
| 16 | +## Problem Description |
| 17 | +You are given a string s of length n, and an integer k. You are tasked to find the longest subsequence repeated k times in string s. |
| 18 | + |
| 19 | +A subsequence is a string that can be derived from another string by deleting some or no characters without changing the order of the remaining characters. |
| 20 | + |
| 21 | +A subsequence seq is repeated k times in the string s if seq * k is a subsequence of s, where seq * k represents a string constructed by concatenating seq k times. |
| 22 | + |
| 23 | +For example, "bba" is repeated 2 times in the string "bababcba", because the string "bbabba", constructed by concatenating "bba" 2 times, is a subsequence of the string "bababcba". |
| 24 | +Return the longest subsequence repeated k times in string s. If multiple such subsequences are found, return the lexicographically largest one. If there is no such subsequence, return an empty string. |
| 25 | + |
| 26 | + |
| 27 | +### Examples |
| 28 | +**Example 1:** |
| 29 | + |
| 30 | + |
| 31 | +``` |
| 32 | +Input: s = "letsleetcode", k = 2 |
| 33 | +Output: "let" |
| 34 | +Explanation: There are two longest subsequences repeated 2 times: "let" and "ete". |
| 35 | +"let" is the lexicographically largest one. |
| 36 | +``` |
| 37 | + |
| 38 | +**Example 2:** |
| 39 | +``` |
| 40 | +Input: s = "bb", k = 2 |
| 41 | +Output: "b" |
| 42 | +Explanation: The longest subsequence repeated 2 times is "b". |
| 43 | +``` |
| 44 | + |
| 45 | +### Constraints |
| 46 | +- `n == s.length` |
| 47 | +- `2 <= n, k <= 2000` |
| 48 | +- `2 <= n < k * 8` |
| 49 | +- `s consists of lowercase English letters.` |
| 50 | + |
| 51 | +## Solution forLongest Subsequence Repeated k Times |
| 52 | + |
| 53 | +### Intuition |
| 54 | + |
| 55 | +To solve this problem, the goal is to find the longest subsequence of `s` that can appear at least `k` times in `s`. This requires checking various subsequences and determining their repeatability. The challenge is to efficiently explore the possible subsequences and verify their validity. |
| 56 | + |
| 57 | +### Approach |
| 58 | +The approach involves a Depth-First Search (DFS) combined with a helper function to verify if a subsequence can be repeated `k` times. Here's a step-by-step breakdown: |
| 59 | + |
| 60 | +1. **DFS Traversal**: |
| 61 | + - Use DFS to explore possible subsequences of `s`. Start with an empty subsequence and try to build it by adding characters from 'z' to 'a' (descending order helps in maximizing the subsequence length early). |
| 62 | + - For each character added, check if the new subsequence can be repeated `k` times in `s`. |
| 63 | + |
| 64 | +2. **Check Repeatability**: |
| 65 | + - Implement a helper function `checkK(s, ans, k)` to verify if the current subsequence `ans` can be repeated `k` times within `s`. |
| 66 | + - This function iterates through `s`, matching characters of `ans` and counting how many times the entire subsequence `ans` appears. |
| 67 | + |
| 68 | +3. **Pruning**: |
| 69 | + - If a subsequence `ans` cannot be repeated `k` times, prune that branch and do not explore further with this subsequence. |
| 70 | + - This reduces unnecessary computations and helps in focusing on potential valid subsequences. |
| 71 | +<Tabs> |
| 72 | + <TabItem value="Solution" label="Solution"> |
| 73 | + |
| 74 | + #### Implementation |
| 75 | + ```jsx live |
| 76 | + function Solution(arr) { |
| 77 | + function checkK(s, ans, k) { |
| 78 | + let j = 0, m = ans.length; |
| 79 | + for (let i = 0; i < s.length; i++) { |
| 80 | + if (s[i] === ans[j]) j++; |
| 81 | + if (j === m) { |
| 82 | + k--; |
| 83 | + if (k === 0) return true; |
| 84 | + j = 0; |
| 85 | + } |
| 86 | + } |
| 87 | + return k <= 0; |
| 88 | + } |
| 89 | + |
| 90 | + function dfs(s, ans, k) { |
| 91 | + let val = 0; |
| 92 | + let r = ""; |
| 93 | + for (let ch = 'z'; ch >= 'a'; ch = String.fromCharCode(ch.charCodeAt(0) - 1)) { |
| 94 | + if (checkK(s, ans + ch, k)) { |
| 95 | + ans += ch; |
| 96 | + let tmp = ch + dfs(s, ans, k); |
| 97 | + if (val < tmp.length) { |
| 98 | + r = tmp; |
| 99 | + val = tmp.length; |
| 100 | + } |
| 101 | + ans = ans.slice(0, -1); |
| 102 | + } |
| 103 | + } |
| 104 | + return r; |
| 105 | + } |
| 106 | + |
| 107 | + function longestSubsequenceRepeatedK(s, k) { |
| 108 | + let ans = ""; |
| 109 | + return dfs(s, ans, k); |
| 110 | + } |
| 111 | + |
| 112 | + const input = "letsleetcode" |
| 113 | + const k =2; |
| 114 | + const output =longestSubsequenceRepeatedK(input ,k) |
| 115 | + return ( |
| 116 | + <div> |
| 117 | + <p> |
| 118 | + <b>Input: </b> |
| 119 | + {JSON.stringify(input)} |
| 120 | + </p> |
| 121 | + <p> |
| 122 | + <b>Output:</b> {output.toString()} |
| 123 | + </p> |
| 124 | + </div> |
| 125 | + ); |
| 126 | + } |
| 127 | + ``` |
| 128 | + |
| 129 | + #### Complexity Analysis |
| 130 | + |
| 131 | + - Time Complexity: $O(n*2^8) $ |
| 132 | + - Space Complexity: $ O(n)$ |
| 133 | + |
| 134 | + ## Code in Different Languages |
| 135 | + <Tabs> |
| 136 | + <TabItem value="JavaScript" label="JavaScript"> |
| 137 | + <SolutionAuthor name="@hiteshgahanolia"/> |
| 138 | + ```javascript |
| 139 | + checkK(s, ans, k) { |
| 140 | + let j = 0, m = ans.length; |
| 141 | + for (let i = 0; i < s.length; i++) { |
| 142 | + if (s[i] === ans[j]) j++; |
| 143 | + if (j === m) { |
| 144 | + k--; |
| 145 | + if (k === 0) return true; |
| 146 | + j = 0; |
| 147 | + } |
| 148 | + } |
| 149 | + return k <= 0; |
| 150 | + } |
| 151 | + |
| 152 | + dfs(s, ans, k) { |
| 153 | + let val = 0; |
| 154 | + let r = ""; |
| 155 | + for (let ch = 'z'; ch >= 'a'; ch = String.fromCharCode(ch.charCodeAt(0) - 1)) { |
| 156 | + if (this.checkK(s, ans + ch, k)) { |
| 157 | + ans += ch; |
| 158 | + let tmp = ch + this.dfs(s, ans, k); |
| 159 | + if (val < tmp.length) { |
| 160 | + r = tmp; |
| 161 | + val = tmp.length; |
| 162 | + } |
| 163 | + ans = ans.slice(0, -1); |
| 164 | + } |
| 165 | + } |
| 166 | + return r; |
| 167 | + } |
| 168 | + |
| 169 | + longestSubsequenceRepeatedK(s, k) { |
| 170 | + let ans = ""; |
| 171 | + return this.dfs(s, ans, k); |
| 172 | + } |
| 173 | + ``` |
| 174 | + |
| 175 | + </TabItem> |
| 176 | + <TabItem value="TypeScript" label="TypeScript"> |
| 177 | + <SolutionAuthor name="@hiteshgahanolia"/> |
| 178 | + ```typescript |
| 179 | + class Solution { |
| 180 | + checkK(s: string, ans: string, k: number): boolean { |
| 181 | + let j = 0, m = ans.length; |
| 182 | + for (let i = 0; i < s.length; i++) { |
| 183 | + if (s[i] === ans[j]) j++; |
| 184 | + if (j === m) { |
| 185 | + k--; |
| 186 | + if (k === 0) return true; |
| 187 | + j = 0; |
| 188 | + } |
| 189 | + } |
| 190 | + return k <= 0; |
| 191 | + } |
| 192 | +
|
| 193 | + dfs(s: string, ans: string, k: number): string { |
| 194 | + let val = 0; |
| 195 | + let r = ""; |
| 196 | + for (let ch = 'z'; ch >= 'a'; ch = String.fromCharCode(ch.charCodeAt(0) - 1)) { |
| 197 | + if (this.checkK(s, ans + ch, k)) { |
| 198 | + ans += ch; |
| 199 | + let tmp = ch + this.dfs(s, ans, k); |
| 200 | + if (val < tmp.length) { |
| 201 | + r = tmp; |
| 202 | + val = tmp.length; |
| 203 | + } |
| 204 | + ans = ans.slice(0, -1); |
| 205 | + } |
| 206 | + } |
| 207 | + return r; |
| 208 | + } |
| 209 | +
|
| 210 | + longestSubsequenceRepeatedK(s: string, k: number): string { |
| 211 | + let ans = ""; |
| 212 | + return this.dfs(s, ans, k); |
| 213 | + } |
| 214 | +} |
| 215 | +
|
| 216 | + ``` |
| 217 | + </TabItem> |
| 218 | + <TabItem value="Python" label="Python"> |
| 219 | + <SolutionAuthor name="@hiteshgahanolia"/> |
| 220 | + ```python |
| 221 | + class Solution: |
| 222 | + def checkK(self, s: str, ans: str, k: int) -> bool: |
| 223 | + j, m = 0, len(ans) |
| 224 | + for i in range(len(s)): |
| 225 | + if s[i] == ans[j]: |
| 226 | + j += 1 |
| 227 | + if j == m: |
| 228 | + k -= 1 |
| 229 | + if k == 0: |
| 230 | + return True |
| 231 | + j = 0 |
| 232 | + return k <= 0 |
| 233 | +
|
| 234 | + def dfs(self, s: str, ans: str, k: int) -> str: |
| 235 | + val = 0 |
| 236 | + r = "" |
| 237 | + for ch in range(ord('z'), ord('a') - 1, -1): |
| 238 | + ch = chr(ch) |
| 239 | + if self.checkK(s, ans + ch, k): |
| 240 | + ans += ch |
| 241 | + tmp = ch + self.dfs(s, ans, k) |
| 242 | + if val < len(tmp): |
| 243 | + r = tmp |
| 244 | + val = len(tmp) |
| 245 | + ans = ans[:-1] |
| 246 | + return r |
| 247 | +
|
| 248 | + def longestSubsequenceRepeatedK(self, s: str, k: int) -> str: |
| 249 | + ans = "" |
| 250 | + return self.dfs(s, ans, k) |
| 251 | +
|
| 252 | + ``` |
| 253 | + |
| 254 | + </TabItem> |
| 255 | + <TabItem value="Java" label="Java"> |
| 256 | + <SolutionAuthor name="@hiteshgahanolia"/> |
| 257 | + ```java |
| 258 | + public class Solution { |
| 259 | + private boolean checkK(String s, String ans, int k) { |
| 260 | + int j = 0, m = ans.length(); |
| 261 | + for (int i = 0; i < s.length(); i++) { |
| 262 | + if (s.charAt(i) == ans.charAt(j)) j++; |
| 263 | + if (j == m) { |
| 264 | + k--; |
| 265 | + if (k == 0) return true; |
| 266 | + j = 0; |
| 267 | + } |
| 268 | + } |
| 269 | + return k <= 0; |
| 270 | + } |
| 271 | +
|
| 272 | + private String dfs(String s, String ans, int k) { |
| 273 | + int val = 0; |
| 274 | + String r = ""; |
| 275 | + for (char ch = 'z'; ch >= 'a'; ch--) { |
| 276 | + if (checkK(s, ans + ch, k)) { |
| 277 | + ans += ch; |
| 278 | + String tmp = ch + dfs(s, ans, k); |
| 279 | + if (val < tmp.length()) { |
| 280 | + r = tmp; |
| 281 | + val = tmp.length(); |
| 282 | + } |
| 283 | + ans = ans.substring(0, ans.length() - 1); |
| 284 | + } |
| 285 | + } |
| 286 | + return r; |
| 287 | + } |
| 288 | +
|
| 289 | + public String longestSubsequenceRepeatedK(String s, int k) { |
| 290 | + String ans = ""; |
| 291 | + return dfs(s, ans, k); |
| 292 | + } |
| 293 | +} |
| 294 | +
|
| 295 | + ``` |
| 296 | + |
| 297 | + </TabItem> |
| 298 | + <TabItem value="C++" label="C++"> |
| 299 | + <SolutionAuthor name="@hiteshgahanolia"/> |
| 300 | + ```cpp |
| 301 | + class Solution { |
| 302 | + bool checkK(string& s, string ans, int k) { |
| 303 | + int j = 0, m = ans.size(); |
| 304 | + for (int i = 0; i < s.size(); i++) { |
| 305 | + if (s[i] == ans[j]) |
| 306 | + j++; |
| 307 | + if (j == m) { |
| 308 | + --k; |
| 309 | + if (k == 0) |
| 310 | + return true; |
| 311 | + j = 0; |
| 312 | + } |
| 313 | + } |
| 314 | + return k <= 0; |
| 315 | + } |
| 316 | + string dfs(string& s, string& ans, int k) { |
| 317 | + int val = 0; |
| 318 | + string r = ""; |
| 319 | + for (char ch = 'z'; ch >= 'a'; ch--) { |
| 320 | + if (checkK(s, ans + ch, k)) { |
| 321 | + ans += ch; |
| 322 | + string tmp = ch + dfs(s, ans, k); |
| 323 | + if (val < tmp.size()) { |
| 324 | + r = tmp; |
| 325 | + val = tmp.size(); |
| 326 | + } |
| 327 | + ans.pop_back(); |
| 328 | + } |
| 329 | + } |
| 330 | + return r; |
| 331 | + } |
| 332 | +
|
| 333 | +public: |
| 334 | + string longestSubsequenceRepeatedK(string s, int k) { |
| 335 | + string ans = ""; |
| 336 | + return dfs(s, ans, k); |
| 337 | + } |
| 338 | +}; |
| 339 | +``` |
| 340 | +</TabItem> |
| 341 | +</Tabs> |
| 342 | + |
| 343 | + </TabItem> |
| 344 | +</Tabs> |
| 345 | + |
| 346 | +## References |
| 347 | + |
| 348 | +- **LeetCode Problem**: [Longest Subsequence Repeated k Times](https://leetcode.com/problems/longest-subsequence-repeated-k-times/description/) |
| 349 | + |
| 350 | +- **Solution Link**: [LeetCode Solution](https://leetcode.com/problems/longest-subsequence-repeated-k-times/description/) |
| 351 | + |
0 commit comments