Description
You are given a string, s, and a list of words, words, that are all of the same length. Find all starting indices of substring(s) in s that is a concatenation of each word in words exactly once and without any intervening characters.
Example
Example 1:
Input:
s = “barfoothefoobarman”,
words = [“foo”,“bar”]
Output: [0,9]
Explanation: Substrings starting at index 0 and 9 are “barfoor” and “foobar” respectively.
The output order does not matter, returning [9,0] is fine too.
Example 2:
Input:
s = “wordgoodstudentgoodword”,
words = [“word”,“student”]
Output: []
Analyse
題目的意思是給定一個字符串s以及一個字符串列表words,讓你找出在s中用words裏面所有單詞排列而成的子串的首位置。
我採用的方法很簡單,就是枚舉s中的所有位置,然後生成一個words列表裏面所有單詞組成的隊列,取出一個,與s匹配,匹配不上的話,就重新壓進隊列,匹配得上的話,位移之後繼續匹配,直到隊列爲空或者隊列裏的元素無減少。稍微做了點剪枝,設s的長度爲s_len,words裏面的單詞長度總和爲word_len,那麼對s的枚舉只需要到s_len-word_len就夠了。時間複雜度爲O(s_len * word_len * word_len),效率是比較差的,然後測試的時候也是剛好在時間點上飄過。優化方法有對單詞進行哈希處理,這樣可以減少比較運算。不過嫌麻煩就沒做了。
Code
class Solution {
public:
bool isCorrect(string& s, string& word, int& temp_pos) {
int word_pos = 0;
while (word_pos < word.length()) {
if (s[temp_pos + word_pos] == word[word_pos]) {
word_pos++;
} else {
return false;
}
}
return true;
}
vector<int> findSubstring(string s, vector<string>& words) {
int len = words.size();
vector<int> ans;
if (s.length() == 0 || words.size() == 0) return ans;
int s_pos = 0;
int total_len = 0;
queue<string> words_queue;
for (int i = 0; i < len; i++) {
words_queue.push(words[i]);
total_len += words[i].length();
}
while (s_pos + total_len <= s.length()) {
queue<string> words_temp = words_queue;
int temp_pos = s_pos;
int count = 0, pre_len = len;
while (!words_temp.empty() && count != pre_len) {
string word = words_temp.front();
words_temp.pop();
if (isCorrect(s, word,temp_pos)) {
temp_pos += word.length();
pre_len--;
count = 0;
} else {
words_temp.push(word);
count++;
}
}
if (words_temp.empty()) {
ans.push_back(s_pos);
}
s_pos++;
}
return ans;
}
};