forked from aylei/leetcode-rust
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathp0030_substring_with_concatenation_of_all_words.rs
142 lines (131 loc) · 4.35 KB
/
p0030_substring_with_concatenation_of_all_words.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/**
* [30] Substring with Concatenation of All Words
*
* You are given a string s and an array of strings words of the same length. Return all starting indices of substring(s) in s that is a concatenation of each word in words exactly once, in any order, and without any intervening characters.
* You can return the answer in any order.
*
* Example 1:
*
* Input: s = "barfoothefoobarman", words = ["foo","bar"]
* Output: [0,9]
* Explanation: Substrings starting at index 0 and 9 are "barfoo" and "foobar" respectively.
* The output order does not matter, returning [9,0] is fine too.
*
* Example 2:
*
* Input: s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]
* Output: []
*
* Example 3:
*
* Input: s = "barfoofoobarthefoobarman", words = ["bar","foo","the"]
* Output: [6,9,12]
*
*
* Constraints:
*
* 1 <= s.length <= 10^4
* s consists of lower-case English letters.
* 1 <= words.length <= 5000
* 1 <= words[i].length <= 30
* words[i] consists of lower-case English letters.
*
*/
pub struct Solution {}
// problem: https://leetcode.com/problems/substring-with-concatenation-of-all-words/
// discuss: https://leetcode.com/problems/substring-with-concatenation-of-all-words/discuss/?currentPage=1&orderBy=most_votes&query=
// submission codes start here
use std::collections::HashMap;
impl Solution {
pub fn find_substring(s: String, words: Vec<String>) -> Vec<i32> {
let substr_len : usize = words[0].len();
let str_len : usize = s.len();
let s : Vec<char> = s.chars().collect(); // into char vec for random access
let substr_count : usize = str_len - substr_len + 1;
let mut matches : Vec<i32> = vec![-1;substr_count];
for i in 0..substr_count {
let sub : String = s[i..i+substr_len].iter().collect();
for (j, word) in words.iter().enumerate() {
if word.eq(&sub) {
matches[i] = j as i32;
}
}
}
// println!("matches = {:?}", matches);
let mut result : Vec<i32> = vec![];
let concat_count : usize = (str_len - substr_len * words.len() + 1) as usize;
let mut default_needed_count : HashMap<String, usize> = HashMap::new();
for word in words.iter() {
*default_needed_count.entry(word.clone()).or_insert(0) +=1;
}
for i in 0..concat_count {
let mut j : usize = i;
let mut needed_count = default_needed_count.clone();
while j < substr_count && matches[j] != -1 {
if let Some(count_ptr) = needed_count.get_mut(&words[matches[j] as usize]) {
if *count_ptr == 0 {
break;
} else {
*count_ptr-=1;
}
}
j += substr_len;
}
if needed_count.values().sum::<usize>() == 0 {
result.push(i as i32);
}
}
result
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_30() {
assert_eq!(
Solution::find_substring(
"wordgoodgoodgoodbestword".to_string(),
vec![
"word".to_string(),
"good".to_string(),
"best".to_string(),
"good".to_string()
]
),
vec![8]
);
assert_eq!(
Solution::find_substring(
"barfoothefoobarman".to_string(),
vec!["foo".to_string(), "bar".to_string()]
),
vec![0, 9]
);
assert_eq!(
Solution::find_substring(
"wordgoodgoodgoodbestword".to_string(),
vec![
"word".to_string(),
"good".to_string(),
"best".to_string(),
"word".to_string()
]
),
vec![]
);
assert_eq!(
Solution::find_substring(
"xxwordgoodgoodgoodbestword".to_string(),
vec![
"word".to_string(),
"good".to_string(),
"best".to_string(),
"good".to_string()
]
),
vec![10]
);
}
}