# 1160. Find Words That Can Be Formed by Characters

## Description

You are given an array of strings words and a string chars.

A string is good if it can be formed by characters from chars (each character can only be used once).

Return the sum of lengths of all good strings in words.

Example 1:

Input: words = ["cat","bt","hat","tree"], chars = "atach"
Output: 6
Explanation: The strings that can be formed are "cat" and "hat" so the answer is 3 + 3 = 6.


Example 2:

Input: words = ["hello","world","leetcode"], chars = "welldonehoneyr"
Output: 10
Explanation: The strings that can be formed are "hello" and "world" so the answer is 5 + 5 = 10.


Constraints:

• 1 <= words.length <= 1000
• 1 <= words[i].length, chars.length <= 100
• words[i] and chars consist of lowercase English letters.

## Solutions

Solution 1: Counting

We can use an array $cnt$ of length $26$ to count the occurrence of each letter in the string $chars$.

Then we traverse the string array $words$. For each string $w$, we use an array $wc$ of length $26$ to count the occurrence of each letter in the string $w$. If for each letter $c$, $wc[c] \leq cnt[c]$, then we can spell the string $w$ with the letters in $chars$, otherwise we cannot spell the string $w$. If we can spell the string $w$, then we add the length of the string $w$ to the answer.

After the traversal, we can get the answer.

The time complexity is $O(L)$, and the space complexity is $O(C)$. Here, $L$ is the sum of the lengths of all strings in the problem, and $C$ is the size of the character set. In this problem, $C = 26$.

• class Solution {
public int countCharacters(String[] words, String chars) {
int[] cnt = new int[26];
for (int i = 0; i < chars.length(); ++i) {
++cnt[chars.charAt(i) - 'a'];
}
int ans = 0;
for (String w : words) {
int[] wc = new int[26];
boolean ok = true;
for (int i = 0; i < w.length(); ++i) {
int j = w.charAt(i) - 'a';
if (++wc[j] > cnt[j]) {
ok = false;
break;
}
}
if (ok) {
ans += w.length();
}
}
return ans;
}
}

• class Solution {
public:
int countCharacters(vector<string>& words, string chars) {
int cnt[26]{};
for (char& c : chars) {
++cnt[c - 'a'];
}
int ans = 0;
for (auto& w : words) {
int wc[26]{};
bool ok = true;
for (auto& c : w) {
int i = c - 'a';
if (++wc[i] > cnt[i]) {
ok = false;
break;
}
}
if (ok) {
ans += w.size();
}
}
return ans;
}
};

• class Solution:
def countCharacters(self, words: List[str], chars: str) -> int:
cnt = Counter(chars)
ans = 0
for w in words:
wc = Counter(w)
if all(cnt[c] >= v for c, v in wc.items()):
ans += len(w)
return ans


• func countCharacters(words []string, chars string) (ans int) {
cnt := [26]int{}
for _, c := range chars {
cnt[c-'a']++
}
for _, w := range words {
wc := [26]int{}
ok := true
for _, c := range w {
c -= 'a'
wc[c]++
if wc[c] > cnt[c] {
ok = false
break
}
}
if ok {
ans += len(w)
}
}
return
}

• function countCharacters(words: string[], chars: string): number {
const idx = (c: string) => c.charCodeAt(0) - 'a'.charCodeAt(0);
const cnt = new Array(26).fill(0);
for (const c of chars) {
cnt[idx(c)]++;
}
let ans = 0;
for (const w of words) {
const wc = new Array(26).fill(0);
let ok = true;
for (const c of w) {
if (++wc[idx(c)] > cnt[idx(c)]) {
ok = false;
break;
}
}
if (ok) {
ans += w.length;
}
}
return ans;
}


• class Solution {
/**
* @param String[] $words * @param String$chars
* @return Integer
*/
function countCharacters($words,$chars) {
$sum = 0; for ($i = 0; $i < strlen($chars); $i++) {$hashtable[$chars[$i]] += 1;
}
for ($j = 0;$j < count($words);$j++) {
$tmp =$hashtable;
$sum += strlen($words[$j]); for ($k = 0; $k < strlen($words[$j]);$k++) {
if (!isset($tmp[$words[$j][$k]]) || $tmp[$words[$j][$k]] === 0) {
$sum -= strlen($words[$j]); break; }$tmp[$words[$j][$k]] -= 1; } } return$sum;
}
}