LeetCode Entry
1639. Number of Ways to Form a Target String Given a Dictionary
precompute the freq array - count of each character at each position
1639. Number of Ways to Form a Target String Given a Dictionary hard
fun numWays(words: Array<String>, target: String): Int {
val freq = Array(words[0].length) { LongArray(26) }
for (i in 0..words[0].lastIndex)
words.forEach { freq[i][it[i].toInt() - 'a'.toInt()]++ }
val cache = Array(words[0].length) { LongArray(target.length) { -1L } }
val m = 1_000_000_007L
fun dfs(wpos: Int, tpos: Int): Long {
if (tpos == target.length) return 1L
if (wpos == words[0].length) return 0L
if (cache[wpos][tpos] != -1L) return cache[wpos][tpos]
val curr = target[tpos].toInt() - 'a'.toInt()
val currFreq = freq[wpos][curr]
val take = if (currFreq == 0L) 0L else
dfs(wpos + 1, tpos + 1)
val notTake = dfs(wpos + 1, tpos)
val mul = (currFreq * take) % m
val res = (mul + notTake) % m
cache[wpos][tpos] = res
return res
}
return dfs(0, 0).toInt()
}
Join me on Telegram
https://t.me/leetcode_daily_unstoppable/182
Intuition
Consider an example: bbc aaa ccc, target = ac. We have 5 ways to form the ac:
// bbc aaa ccc ac
// a c
// a c
// c a
// a c
// c a
Looking at this, we deduce, that only count of every character at every position matter.
// 0 -> 1b 1a 1c
// 1 -> 1b 1a 1c
// 2 -> 1a 2c
To form ac we can start from position 0 or from 1. If we start at 0, we have one c at 1 plus two c at 2. And if we start at 1 we have two c at 3.
\(DP_{i,j} = Freq * DP_{i + 1, j + 1} + DP_{i + 1, j}\)
Approach
- precompute the
freqarray - count of each character at each position - use an
Arrayfor faster cache - use
longto avoid overflowComplexity
- Time complexity: \(O(n^2)\)
- Space complexity: \(O(n^2)\)