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;
    }
    
    

All Problems

All Solutions