ΠΠ°Π΄Π°ΡΠ° - 1639. Number of Ways to Form a Target String Given a Dictionary
π ΠΠΏΠΈΡΠ°Π½ΠΈΠ΅ Π·Π°Π΄Π°ΡΠΈ
ΠΠ°Π½ΠΎ: ΡΠΏΠΈΡΠΎΠΊ ΡΡΡΠΎΠΊ words ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎΠΉ Π΄Π»ΠΈΠ½Ρ ΠΈ ΡΡΡΠΎΠΊΠ° target
.
Π¦Π΅Π»Ρ: ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈΡΡ, ΡΠΊΠΎΠ»ΡΠΊΠΈΠΌΠΈ ΡΠΏΠΎΡΠΎΠ±Π°ΠΌΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΡΠΎΠ±ΡΠ°ΡΡ ΡΡΡΠΎΠΊΡ target
, ΡΠ»Π΅Π΄ΡΡ ΠΏΡΠ°Π²ΠΈΠ»Π°ΠΌ:
- Π ΠΎΡΠ΅ΡΠ΅Π΄Π½ΠΎΠΉ ΡΠ°Π³ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΠΈΠΌΠ²ΠΎΠ», ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡΡΠΈΠΉ Ρ Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΡΠΌ ΠΎΡΠ΅ΡΠ΅Π΄Π½ΡΠΌ ΡΠΈΠΌΠ²ΠΎΠ»ΠΎΠΌ
target
, ΠΈΠ· Π»ΡΠ±ΠΎΠΉ Π΄ΠΎΠΏΡΡΡΠΈΠΌΠΎΠΉ ΠΏΠΎΠ·ΠΈΡΠΈΠΈ ΡΠ°Π±Π»ΠΈΡΡ words
.
- ΠΠΎΡΠ»Π΅ Π²ΡΠ±ΠΎΡΠ° ΡΠΈΠΌΠ²ΠΎΠ»Π° ΠΈΠ· ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ½Π½ΠΎΠΉ ΠΏΠΎΠ·ΠΈΡΠΈΠΈ Π²ΡΠ΅ ΡΠΈΠΌΠ²ΠΎΠ»Ρ Π²ΡΠ΅Ρ
ΡΠ»ΠΎΠ² Π»Π΅Π²Π΅Π΅ ΠΈΠ»ΠΈ ΡΠ°Π²Π½ΡΠ΅ ΡΡΠΎΠΉ ΠΏΠΎΠ·ΠΈΡΠΈΠΈ ΡΡΠ°Π½ΠΎΠ²ΡΡΡΡ Π½Π΅Π΄ΠΎΡΡΡΠΏΠ½ΡΠΌΠΈ.
- ΠΠ΅ΡΠ½ΡΡΡ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΡΠΏΠΎΡΠΎΠ±ΠΎΠ² ΠΏΠΎ ΠΌΠΎΠ΄ΡΠ»Ρ
1_000_000_007
π‘ ΠΠ΄Π΅Ρ
ΠΡ ΠΌΠΎΠΆΠ΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΏΠΎΠ΄Ρ
ΠΎΠ΄ Π΄ΠΈΠ½Π°ΠΌΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΡ. ΠΠ»Ρ Π±ΡΡΡΡΠΎΠ³ΠΎ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΡ ΡΠΎΡΡΠΎΡΠ½ΠΈΠΉ ΠΠ ΠΏΡΠ΅Π΄Π²Π°ΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΏΠΎΠ΄ΡΡΠΈΡΠ°Π΅ΠΌ ΡΠ°ΡΡΠΎΡΡ ΡΠΈΠΌΠ²ΠΎΠ»ΠΎΠ² Π΄Π»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΏΠΎΠ·ΠΈΡΠΈΠΈ Π² words
.
Π€ΠΎΡΠΌΡΠ»Π° ΠΠ:
ΠΡΡΡΡ dp[i][j]
β ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΡΠΏΠΎΡΠΎΠ±ΠΎΠ² ΡΠΎΠ±ΡΠ°ΡΡ ΠΏΠ΅ΡΠ²ΡΠ΅ i
ΡΠΈΠΌΠ²ΠΎΠ»ΠΎΠ² ΡΡΡΠΎΠΊΠΈ target, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡ ΠΏΠ΅ΡΠ²ΡΠ΅ j
-ΠΉ ΠΏΠΎΠ·ΠΈΡΠΈΠΈ Π² ΡΡΡΠΎΠΊΠ°Ρ
words
. Π’ΠΎΠ³Π΄Π°:
dp[i][j] = dp[i][jβ1] + dp[iβ1][jβ1]β
freqj(target[i]])
, Π³Π΄Π΅:
dp[i][jβ1]
β ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΡΠΏΠΎΡΠΎΠ±ΠΎΠ² ΡΠΎΠ±ΡΠ°ΡΡ ΠΏΠ΅ΡΠ²ΡΠ΅ i
ΡΠΈΠΌΠ²ΠΎΠ»ΠΎΠ² target, ΠΈΠ³Π½ΠΎΡΠΈΡΡΡ j
-Ρ ΠΏΠΎΠ·ΠΈΡΠΈΡ.
freqj(c)
β ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ Π²Ρ
ΠΎΠΆΠ΄Π΅Π½ΠΈΠΉ ΡΠΈΠΌΠ²ΠΎΠ»Π° c
Π² j
-ΠΎΠΌ ΡΡΠΎΠ»Π±ΡΠ΅ words
.
dp[iβ1][jβ1]β
freqj(target[i]])
β ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΡΠΏΠΎΡΠΎΠ±ΠΎΠ² Π΄ΠΎΠ±Π°Π²ΠΈΡΡ ΡΠ»Π΅ΠΌΠ΅Π½Ρ ΠΈΠ· j
-Π³ΠΎ ΡΡΠΎΠ»Π±ΡΠ° words
Π΄Π»Ρ ΡΠΈΠΌΠ²ΠΎΠ»Π° target[i]
, ΠΎΠΏΠΈΡΠ°ΡΡΡ Π½Π° ΡΠΆΠ΅ ΡΠΎΠ±ΡΠ°Π½Π½ΡΠ΅ iβ1
ΡΠΈΠΌΠ²ΠΎΠ»ΠΎΠ².
ΠΡ ΠΎΠΏΡΠΈΠΌΠΈΠ·ΠΈΡΡΠ΅ΠΌ ΠΏΠ°ΠΌΡΡΡ, ΡΠ²ΠΎΡΠ°ΡΠΈΠ²Π°Ρ Π΄Π²ΡΠΌΠ΅ΡΠ½ΡΠΉ ΠΌΠ°ΡΡΠΈΠ² dp[i][j]
Π² ΠΎΠ΄Π½ΠΎΠΌΠ΅ΡΠ½ΡΠΉ ΠΌΠ°ΡΡΠΈΠ² dp[j]
, ΡΠΎΡ
ΡΠ°Π½ΡΡ ΡΠΎΠ»ΡΠΊΠΎ ΡΠ΅ΠΊΡΡΠΈΠΉ ΡΠ»ΠΎΠΉ ΠΈ Π΄ΠΈΠ°Π³ΠΎΠ½Π°Π»ΡΠ½ΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ Π΄Π»Ρ ΠΏΡΠ΅Π΄ΡΠ΄ΡΡΠ΅Π³ΠΎ ΡΠ»ΠΎΡ.
π ΠΠ΅ΡΠ°Π»ΠΈ ΠΏΠΎΠ΄Ρ
ΠΎΠ΄Π°
-
ΠΡΠ΅Π΄ΠΏΠΎΠ΄ΡΡΠ΅Ρ ΡΠ°ΡΡΠΎΡ ΡΠΈΠΌΠ²ΠΎΠ»ΠΎΠ²:
- ΠΠ»Ρ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΈΠ·
26
Π±ΡΠΊΠ² Π°Π»ΡΠ°Π²ΠΈΡΠ° ΠΏΠΎΠ΄ΡΡΠΈΡΠ°Π΅ΠΌ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΠΈΡ
Π²Ρ
ΠΎΠΆΠ΄Π΅Π½ΠΈΠΉ Π½Π° ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΏΠΎΠ·ΠΈΡΠΈΠΈ Π² ΡΡΡΠΎΠΊΠ°Ρ
words
. ΠΡΠΎ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ Π½Π°ΠΌ Π±ΡΡΡΡΠΎ ΠΏΡΠΎΠ²Π΅ΡΡΡΡ, ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΠ°Π· Π½ΡΠΆΠ½ΡΠΉ ΡΠΈΠΌΠ²ΠΎΠ» Π΄ΠΎΡΡΡΠΏΠ΅Π½ Π² ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΏΠΎΠ·ΠΈΡΠΈΠΈ.
-
Π Π°ΡΡΡΡ ΡΠ°Π±Π»ΠΈΡΡ Π΄ΠΈΠ½Π°ΠΌΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΡ:
- ΠΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ ΠΌΠ°ΡΡΠΈΠ²
dp
, Π³Π΄Π΅ dp[j]
Ρ
ΡΠ°Π½ΠΈΡ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΡΠΏΠΎΡΠΎΠ±ΠΎΠ² ΡΠΎΠ±ΡΠ°ΡΡ ΡΠ΅ΠΊΡΡΡΡ ΠΏΠΎΠ΄ΡΡΡΠΎΠΊΡ target
Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΏΠ΅ΡΠ²ΡΡ
j
-ΠΉ ΠΏΠΎΠ·ΠΈΡΠΈΠΉ ΠΈΠ· words
- ΠΠ»Ρ ΠΎΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΠΈ ΠΏΠ°ΠΌΡΡΠΈ ΡΠΎΡ
ΡΠ°Π½ΡΠ΅ΠΌ ΡΠΎΠ»ΡΠΊΠΎ ΠΎΠ΄ΠΈΠ½ ΡΠ»ΠΎΠΉ
DP
ΠΈ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ diag_val
Π΄Π»Ρ Ρ
ΡΠ°Π½Π΅Π½ΠΈΡ Π΄ΠΈΠ°Π³ΠΎΠ½Π°Π»ΡΠ½ΠΎΠ³ΠΎ Π·Π½Π°ΡΠ΅Π½ΠΈΡ.
-
ΠΠΎΠ΄ΡΠ»ΡΠ½Π°Ρ Π°ΡΠΈΡΠΌΠ΅ΡΠΈΠΊΠ°:
- Π§ΡΠΎΠ±Ρ ΠΈΠ·Π±Π΅ΠΆΠ°ΡΡ ΠΏΠ΅ΡΠ΅ΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ
i32
, Π²ΡΠ΅ ΠΏΡΠΎΠΌΠ΅ΠΆΡΡΠΎΡΠ½ΡΠ΅ Π²ΡΡΠΈΡΠ»Π΅Π½ΠΈΡ Π²ΡΠΏΠΎΠ»Π½ΡΡΡΡΡ Π² i64
Ρ ΠΏΠΎΡΠ»Π΅Π΄ΡΡΡΠΈΠΌ ΠΏΡΠΈΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ΠΌ ΠΎΠ±ΡΠ°ΡΠ½ΠΎ ΠΊ i32
.
β±οΈ ΠΡΠΈΠΌΠΏΡΠΎΡΠΈΠΊΠΈ
-
ΠΡΠ΅ΠΌΡ:
O(nβ
m)
: ΠΠ»Ρ ΠΏΠΎΡΡΡΠΎΠ΅Π½ΠΈΡ ΡΠ°ΡΡΠΎΡ ΡΠΈΠΌΠ²ΠΎΠ»ΠΎΠ² (n
β ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΡΡΡΠΎΠΊ, m
β Π΄Π»ΠΈΠ½Π° ΡΡΡΠΎΠΊΠΈ).
O(kβ
m)
: ΠΠ»Ρ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΡ DP
(k
β Π΄Π»ΠΈΠ½Π° target).
- ΠΡΠΎΠ³ΠΎ:
O((n+k)β
m)
-
ΠΠ°ΠΌΡΡΡ:
O(26β
m)
: ΠΠ»Ρ ΡΠ°ΡΡΠΎΡ ΡΠΈΠΌΠ²ΠΎΠ»ΠΎΠ².
O(m)
: ΠΠ»Ρ ΠΌΠ°ΡΡΠΈΠ²Π° dp.
- ΠΡΠΎΠ³ΠΎ:
O(m)
.
π ΠΡΡ
ΠΎΠ΄Π½ΡΠΉ ΠΊΠΎΠ΄
impl Solution {
pub fn num_ways(words: Vec<String>, target: String) -> i32 {
const MOD: i32 = 1_000_000_007;
let word_length = words[0].len();
let target_length = target.len();
// Edge case: If the target is longer than the word length, it's impossible
if target_length > word_length {
return 0;
}
// Step 1: Build letter counters
let letter_counters = Self::build_letter_counters(&words, word_length);
// Step 2: Compute the number of ways using dynamic programming
Self::compute_ways(&target, &letter_counters, word_length, target_length, MOD)
}
fn build_letter_counters(words: &Vec<String>, word_length: usize) -> [Vec<i32>; 26] {
// Initialize a fixed-size array of 26 vectors using Default::default()
let mut letter_counters: [Vec<i32>; 26] = Default::default();
for vec in &mut letter_counters {
*vec = vec![0; word_length];
}
for word in words {
for (j, c) in word.bytes().enumerate() {
letter_counters[(c - b'a') as usize][j] += 1;
}
}
letter_counters
}
fn compute_ways(
target: &String,
letter_counters: &[Vec<i32>; 26],
word_length: usize,
target_length: usize,
mod_val: i32,
) -> i32 {
let target_bytes = target.as_bytes();
// Initialize the DP array for the first target character
let mut dp = vec![0; word_length];
let first_char_counters = &letter_counters[(target_bytes[0] - b'a') as usize];
dp[0] = first_char_counters[0];
for j in 1..word_length {
dp[j] = (first_char_counters[j] + dp[j - 1]) % mod_val;
}
// Process subsequent target characters
for i in 1..target_length {
let mut diag_val = 0;
let current_char_counters = &letter_counters[(target_bytes[i] - b'a') as usize];
diag_val = dp[i - 1];
dp[i - 1] = 0;
for j in i..word_length {
let new_diag_val = dp[j];
dp[j] = ((dp[j - 1] as i64 + diag_val as i64 * current_char_counters[j] as i64) % mod_val as i64) as i32;
diag_val = new_diag_val;
}
}
dp[word_length - 1]
}
}