Number of Ways to Form a Target String Given a Dictionary
You are given a list of strings wordstargettarget
- to form the j-th character of
, pick a character at some columntarget of any word that matches it;col - after using column
, no column at or beforecol may be used again, in any word.col
Return the number of ways to form target
Example 1
Output: 6
Example 2
Output: 4
How to Think About It
Step 1: Only the columns matter, not the words
When we take a character from column colcount[col][letter]
Step 2: Define the subproblem
Let ways[j]jtargetways[0] = 1
Step 3: Process one column at a time
For a new column colj
- skip the column: the old
stays;ways[j] - use the column for character j: extend any way of forming
characters, choosing one of thej - 1 words that have the right letter here.count[col][target[j - 1]]
ways[j] = ways[j] + ways[j - 1] × count[col][target[j - 1]]
Step 4: Go through j backwards
Updating jways[j - 1]
Walkthrough
words = ["abba", "baab"]target = "bab"
| After column | ways[0] | ways[1] ("b") | ways[2] ("ba") | ways[3] ("bab") |
|---|---|---|---|---|
| start | 1 | 0 | 0 | 0 |
| 0 | 1 | 1 | 0 | 0 |
| 1 | 1 | 2 | 1 | 0 |
| 2 | 1 | 3 | 3 | 1 |
| 3 | 1 | 4 | 6 | 4 |
The answer is ways[3] = 4
Java Solution
The inner loop starts at min(m, col + 1)col + 1col + 1
public class NumberOfWaysToFormTargetString {
private static final int MOD = 1_000_000_007;
public static int numWays(String[] words, String target) {
int len = words[0].length();
int m = target.length();
int[][] count = new int[len][26]; // count[col][c]: words with letter c in column col
for (String w : words) {
for (int col = 0; col < len; col++) {
count[col][w.charAt(col) - 'a']++;
}
}
// ways[j]: ways to build the first j letters of target using the columns seen so far
long[] ways = new long[m + 1];
ways[0] = 1;
for (int col = 0; col < len; col++) {
for (int j = Math.min(m, col + 1); j >= 1; j--) { // backwards: use col once
int c = target.charAt(j - 1) - 'a';
ways[j] = (ways[j] + ways[j - 1] * count[col][c]) % MOD;
}
}
return (int) ways[m];
}
public static void main(String[] args) {
System.out.println(numWays(new String[] {"acca", "bbbb", "caca"}, "aba")); // 6
System.out.println(numWays(new String[] {"abba", "baab"}, "bab")); // 4
}
}
Complexity
- Time: O(w × L + L × m), where w is the number of words, L their length and m the target's length: counting, then the table.
- Space: O(26 × L + m).
Processing items one at a time and updating a one-dimensional table backwards is the same pattern as in