LC30 Substring with Concatenation of All Words

这题和LC76 Minimum Window Substring可以归为一类,就是给出要找的字符(字符串)和相应个数,利用滑动窗口在另一个字符串上找。类似的题目还有LC3。

首先需要用map把出现的单词和相应出现的次数记录下来。

然后维护一个窗口,一步步往前移动。每移动一次就检查是否满足条件。解题时注意每个单词的长度是固定的,这一点给解题带来很大方便。

 1 class Solution{
 2 public:
 3 vector<int> findSubstring(string S, vector<string> &L) {  
 4         map<string,int> words;  
 5         map<string,int> cur;  
 6         int wordNum = L.size();  
 7         for(int i = 0; i < wordNum; i++)  
 8             words[L[i]]++;  
 9         int wordLen = L[0].size();  
10         vector<int> res;  
11         for(int i = 0; i <= (int)S.size()-wordLen*wordNum; i++)  
12         {  
13             cur.clear();  
14             int j;  
15             for(j = 0; j < wordNum; j++)  
16             {  
17                 string word = S.substr(i+j*wordLen, wordLen);  
18                 if(words.find(word) == words.end())  
19                     break;  
20                 cur[word]++;  
21                 if(cur[word]>words[word])  
22                     break;  
23             }  
24             if(j == wordNum)  
25                 res.push_back(i);  
26         }  
27         return res;  
28     }  
29 };
View Code

 以上程序需要维护两个map,其中一个用于循环后复原初始map。这造成了空间上的浪费。此外,移动一次仅仅移动一步,这对效率而言也是损害。

其实,移动可以分为两种,一种是开始坐标的移动,这种移动每次移动1步,但最多只需移动一个单词长度即可。另一种移动则按单词长度来移动。这样维护的窗口能更有效地找到结果,具体思路和LC76 Minimum Window Substring 类似。

小细节需要注意的是,对于map容器,以下代码:

1 if(imap.find("u")==imap.end())
2     imap.insert(make_pair("u",1));
3 else
4     imap["u"]++;

可以直接用一句话(效率更高)代替

imap["u"]++;

如果"u"一开始不存在,imap["u"]会初始化为0。

另外unordered_map比map查询速度要快。

 1 class Solution {
 2 public:
 3     vector<int> findSubstring(string s, vector<string>& words) {
 4         vector<int> result;
 5         if (words.size() == 0) {
 6             return result;
 7         }
 8         unordered_map<string, int> hash;
 9         for (int i = 0; i < words.size(); i++) {
10             hash[words[i]]++;
11         }
12         int wSize = words[0].length();
13         for (int start = 0; start < wSize; start++) {
14             int wCount = 0;
15             unordered_map<string, int> slidingWindow;
16             for (int i = start; i + wSize <= s.length(); i+=wSize) {
17                 string word = s.substr(i, wSize);
18                 if (hash.find(word) == hash.end()) {
19                     slidingWindow.clear();
20                     wCount = 0;
21                 } else {
22                     wCount++;
23                     slidingWindow[word]++;
24                     while (hash[word] < slidingWindow[word]) {
25                         string removedWord = s.substr(i - (wCount-1) * wSize, wSize);
26                         slidingWindow[removedWord]--;
27                         wCount--;
28                     }
29                 }
30                 if (wCount == words.size()) {
31                     result.push_back(i - (wCount - 1) * wSize);
32                 }
33             }
34         }
35         return result;
36     }
37 };
View Code

(用哈希数组记录单词出现次数,别想着以后碰到了单词可以将对应值减1,然后到了一定时候用取巧的方法判断数组是否都为0 。换言之,貌似除了循环,没有什么取巧的函数可以判断一个整型数组是否都为0)

posted @ 2016-04-05 15:50  vaevaevae  阅读(167)  评论(0编辑  收藏  举报