Skip to content

Commit 402dac4

Browse files
committed
update 30 Substring with Concatenation of All Words
1 parent 7b59ca8 commit 402dac4

File tree

4 files changed

+247
-52
lines changed

4 files changed

+247
-52
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
* @Author: [email protected]
3+
* @Last Modified time: 2016-07-12 18:58:58
4+
*/
5+
6+
class Solution {
7+
public:
8+
// Easy to understand but slow.
9+
vector<int> findSubstring(string s, vector<string>& words) {
10+
int s_len = s.size();
11+
int w_len = words.size();
12+
if(s_len == 0 || w_len==0){
13+
return {};
14+
}
15+
16+
int wl = words[0].size();
17+
int str_len = w_len * words[0].size();
18+
unordered_map<string, int> word_cnt;
19+
for(auto &w: words){
20+
word_cnt[w] += 1;
21+
}
22+
vector<int> ans;
23+
for(int i=0; i<s_len-str_len+1; i++){
24+
unordered_map<string, int> tmp_cnt;
25+
int j=0;
26+
while(j<w_len){
27+
string cur_word = s.substr(i+j*wl, wl);
28+
if(word_cnt.find(cur_word)==word_cnt.end()){
29+
break;
30+
}
31+
else{
32+
tmp_cnt[cur_word] ++;
33+
if(tmp_cnt[cur_word] > word_cnt[cur_word]){
34+
break;
35+
}
36+
}
37+
j++;
38+
}
39+
if(j == w_len){
40+
ans.push_back(i);
41+
}
42+
}
43+
return ans;
44+
}
45+
};
46+
47+
48+
class Solution_2 {
49+
public:
50+
/*
51+
Use hashmap and two point.
52+
53+
Travel all the words combinations to maintain a slicing window.
54+
There are wl(word len) times travel, each time n/wl words:
55+
mostly 2 times travel for each word:
56+
one left side of the window, the other right side of the window
57+
So, time complexity O(wl * 2 * N/wl) = O(2N)
58+
Refer to:
59+
https://discuss.leetcode.com/topic/6617/an-o-n-solution-with-detailed-explanation
60+
*/
61+
vector<int> findSubstring(string s, vector<string>& words) {
62+
int s_len = s.size();
63+
int total_cnt = words.size();
64+
if(s_len == 0 || total_cnt==0){
65+
return {};
66+
}
67+
68+
int w_len = words[0].size();
69+
unordered_map<string, int> words_cnt;
70+
for(auto &w: words){
71+
words_cnt[w] ++;
72+
}
73+
74+
vector<int> ans;
75+
for(int i=0; i<w_len; i++){
76+
int left=i, count=0;
77+
unordered_map<string, int> candidate_cnt;
78+
for(int j=i; j<=s_len-w_len; j+=w_len){
79+
string cur_str = s.substr(j, w_len);
80+
if(words_cnt.find(cur_str) != words_cnt.end()){
81+
candidate_cnt[cur_str] ++;
82+
count += 1;
83+
if(candidate_cnt[cur_str] > words_cnt[cur_str]){
84+
// A more word, advance the window left side possiablly
85+
while(candidate_cnt[cur_str] > words_cnt[cur_str]){
86+
string left_str = s.substr(left, w_len);
87+
candidate_cnt[left_str] --;
88+
left += w_len;
89+
count --;
90+
}
91+
}
92+
// come to a result
93+
if(count == total_cnt){
94+
ans.push_back(left);
95+
candidate_cnt[s.substr(left, w_len)] --;
96+
count --;
97+
left += w_len;
98+
}
99+
}
100+
else{
101+
left = j+w_len;
102+
candidate_cnt = {};
103+
count = 0;
104+
}
105+
}
106+
}
107+
return ans;
108+
}
109+
};
110+
111+
112+
/*
113+
""
114+
[]
115+
"barfoothefoobarman"
116+
["foo", "bar"]
117+
"barfoofoobarthefoobarman"
118+
["bar","foo","the"]
119+
*/
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
#! /usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
# @Last Modified time: 2016-07-12 18:57:50
5+
6+
7+
class Solution(object):
8+
""" Easy to think, but is very slow.
9+
10+
Use an unordered_map<string, int> counts to record the expected times of each word and
11+
another unordered_map<string, int> seen to record the times we have seen
12+
"""
13+
14+
def findSubstring(self, s, words):
15+
if not s or not words:
16+
return []
17+
18+
word_cnt = {}
19+
for w in words:
20+
word_cnt[w] = word_cnt.get(w, 0) + 1
21+
22+
s_len, word_l = len(s), len(words[0])
23+
concatenation_l = len(words) * word_l
24+
ans = []
25+
for i in range(s_len - concatenation_l + 1):
26+
candidate_map = {}
27+
j = 0
28+
while j < len(words):
29+
w = s[i + j * word_l: i + (j + 1) * word_l]
30+
if w not in word_cnt:
31+
break
32+
candidate_map[w] = candidate_map.get(w, 0) + 1
33+
if candidate_map.get(w, 0) > word_cnt[w]:
34+
break
35+
j += 1
36+
37+
if j == len(words):
38+
ans.append(i)
39+
40+
return ans
41+
42+
43+
class Solution_2(object):
44+
""" Use hashmap and two point.
45+
46+
Travel all the words combinations to maintain a slicing window.
47+
There are wl(word len) times travel, each time n/wl words:
48+
mostly 2 times travel for each word:
49+
one left side of the window, the other right side of the window
50+
So, time complexity O(wl * 2 * N/wl) = O(2N)
51+
Refer to:
52+
https://discuss.leetcode.com/topic/6617/an-o-n-solution-with-detailed-explanation
53+
"""
54+
def findSubstring(self, s, words):
55+
if not s or not words:
56+
return []
57+
58+
word_cnt = {}
59+
for w in words:
60+
word_cnt[w] = word_cnt.get(w, 0) + 1
61+
62+
s_len, w_len, cnt = len(s), len(words[0]), len(words)
63+
i = 0
64+
ans = []
65+
while i < w_len:
66+
left, count = i, 0
67+
candidate_cnt = {}
68+
for j in range(i, s_len, w_len):
69+
cur_str = s[j: j + w_len]
70+
if cur_str in word_cnt:
71+
candidate_cnt[cur_str] = candidate_cnt.get(cur_str, 0) + 1
72+
count += 1
73+
if candidate_cnt[cur_str] <= word_cnt[cur_str]:
74+
pass
75+
else:
76+
# A more word, advance the window left side possiablly
77+
while candidate_cnt[cur_str] > word_cnt[cur_str]:
78+
left_str = s[left: left + w_len]
79+
candidate_cnt[left_str] -= 1
80+
left += w_len
81+
count -= 1
82+
83+
# come to a result
84+
if count == cnt:
85+
ans.append(left)
86+
candidate_cnt[s[left:left + w_len]] -= 1
87+
count -= 1
88+
left += w_len
89+
# not a valid word, clear the window.
90+
else:
91+
candidate_cnt = {}
92+
left = j + w_len
93+
count = 0
94+
i += 1
95+
return ans
96+
97+
98+
class Solution_Fail(object):
99+
""" Pythonic way, easy to think, but Time Limit Exceeded.
100+
101+
Use two hash-map.
102+
"""
103+
def findSubstring(self, s, words):
104+
if not s or not words:
105+
return []
106+
import collections
107+
word_cnt = collections.Counter(words)
108+
s_len, word_l = len(s), len(words[0])
109+
concatenation_l = len(words) * word_l
110+
ans = []
111+
for i in range(s_len - concatenation_l + 1):
112+
candidate_str = s[i:i + concatenation_l]
113+
split_str = [candidate_str[j:j + word_l]
114+
for j in range(0, concatenation_l, word_l)]
115+
candidate_cnt = collections.Counter(split_str)
116+
if not (word_cnt - candidate_cnt):
117+
ans.append(i)
118+
return ans
119+
120+
"""
121+
""
122+
[]
123+
"barfoothefoobarman"
124+
["foo", "bar"]
125+
"barfoofoobarthefoobarman"
126+
["bar","foo","the"]
127+
"""

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@
306306

307307
# Combination
308308

309+
* 030. [Substring with Concatenation of All Words](Combination/30_SubstringWithConcatenationOfAllWords.py)
309310
* 140. [Word Break II](Combination/140_WordBreakII.py)
310311
* 146. [LRU Cache](Combination/146_LRUCache.py)
311312
* 300. [Longest Increasing Subsequence](Combination/300_LongestIncreasingSubsequence.py)

Week04/30.py

Lines changed: 0 additions & 52 deletions
This file was deleted.

0 commit comments

Comments
 (0)