Welcome to Subscribe On Youtube
1239. Maximum Length of a Concatenated String with Unique Characters
Description
You are given an array of strings arr
. A string s
is formed by the concatenation of a subsequence of arr
that has unique characters.
Return the maximum possible length of s
.
A subsequence is an array that can be derived from another array by deleting some or no elements without changing the order of the remaining elements.
Example 1:
Input: arr = ["un","iq","ue"] Output: 4 Explanation: All the valid concatenations are: - "" - "un" - "iq" - "ue" - "uniq" ("un" + "iq") - "ique" ("iq" + "ue") Maximum length is 4.
Example 2:
Input: arr = ["cha","r","act","ers"] Output: 6 Explanation: Possible longest valid concatenations are "chaers" ("cha" + "ers") and "acters" ("act" + "ers").
Example 3:
Input: arr = ["abcdefghijklmnopqrstuvwxyz"] Output: 26 Explanation: The only string in arr has all 26 characters.
Constraints:
1 <= arr.length <= 16
1 <= arr[i].length <= 26
arr[i]
contains only lowercase English letters.
Solutions
Solution 1: Bit Manipulation + State Compression
State compression is used, with a 32-bit number recording the occurrence of letters, and masks
storing the strings enumerated before.
The time complexity is $O(2^n + L)$, and the space complexity is $O(2^n)$. Where $n$ and $L$ are the length of the string array and the sum of the lengths of the strings in the array, respectively.
-
class Solution { public int maxLength(List<String> arr) { int ans = 0; List<Integer> masks = new ArrayList<>(); masks.add(0); for (var s : arr) { int mask = 0; for (int i = 0; i < s.length(); ++i) { int j = s.charAt(i) - 'a'; if (((mask >> j) & 1) == 1) { mask = 0; break; } mask |= 1 << j; } if (mask == 0) { continue; } int n = masks.size(); for (int i = 0; i < n; ++i) { int m = masks.get(i); if ((m & mask) == 0) { masks.add(m | mask); ans = Math.max(ans, Integer.bitCount(m | mask)); } } } return ans; } }
-
class Solution { public: int maxLength(vector<string>& arr) { int ans = 0; vector<int> masks = {0}; for (auto& s : arr) { int mask = 0; for (auto& c : s) { int i = c - 'a'; if (mask >> i & 1) { mask = 0; break; } mask |= 1 << i; } if (mask == 0) { continue; } int n = masks.size(); for (int i = 0; i < n; ++i) { int m = masks[i]; if ((m & mask) == 0) { masks.push_back(m | mask); ans = max(ans, __builtin_popcount(m | mask)); } } } return ans; } };
-
class Solution: def maxLength(self, arr: List[str]) -> int: ans = 0 masks = [0] for s in arr: mask = 0 for c in s: i = ord(c) - ord('a') if mask >> i & 1: mask = 0 break mask |= 1 << i if mask == 0: continue for m in masks: if m & mask == 0: masks.append(m | mask) ans = max(ans, (m | mask).bit_count()) return ans
-
func maxLength(arr []string) (ans int) { masks := []int{0} for _, s := range arr { mask := 0 for _, c := range s { i := int(c - 'a') if mask>>i&1 == 1 { mask = 0 break } mask |= 1 << i } if mask == 0 { continue } n := len(masks) for _, m := range masks[:n] { if m&mask == 0 { masks = append(masks, m|mask) ans = max(ans, bits.OnesCount(uint(m|mask))) } } } return }
-
function maxLength(arr: string[]): number { const s: number[] = [0]; let ans = 0; for (const t of arr) { let x = 0; for (const c of t) { const b = c.charCodeAt(0) - 97; if ((x >> b) & 1) { x = 0; break; } x |= 1 << b; } if (x > 0) { for (let i = s.length - 1; ~i; --i) { const y = s[i]; if ((x & y) === 0) { s.push(x | y); ans = Math.max(ans, bitCount(x | y)); } } } } return ans; } function bitCount(i: number): number { i = i - ((i >>> 1) & 0x55555555); i = (i & 0x33333333) + ((i >>> 2) & 0x33333333); i = (i + (i >>> 4)) & 0x0f0f0f0f; i = i + (i >>> 8); i = i + (i >>> 16); return i & 0x3f; }