19.1.30 [LeetCode 30] Substring with Concatenation of All Words

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 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 = "wordgoodgoodgoodbestword",
  words = ["word","good","best","word"]
Output: []

题意

给定字符串s和字符串数组words,对于words中所有字符串任意顺序组合而成的字符串,如果是s的子串的求出在s中出现的所有索引。

题解

一开始暴力TLE了

 1 class Solution {
 2 public:
 3     set<int>ans;
 4     void findstr(string s,string now,deque<string>&words) {
 5         if (words.empty()) {
 6             int idx = s.find(now), base = 0;
 7             while (idx != string::npos) {
 8                 ans.insert(idx+base);
 9                 base = base + idx + 1;
10                 s=s.substr(idx + 1);
11                 idx = s.find(now);
12             }
13             return;
14         }
15         int size = words.size();
16         for (int i = 0; i < size; i++) {
17             string tmp = words[size-1];
18             words.pop_back();
19             findstr(s, now + tmp, words);
20             words.push_front(tmp);
21         }
22         return;
23     }
24     vector<int> findSubstring(string s, vector<string>& words) {
25         if (s == "" || words.size() == 0)return vector<int>();
26         deque<string>wwords;
27         for (int i = 0; i < words.size(); i++)
28             wwords.push_back(words[i]);
29         findstr(s, "", wwords);
30         return vector<int>(ans.begin(),ans.end());
31     }
32 };
View Code

 后来搞了种非常混乱的方法,类似于之前有道题的滑动窗口(要看清所有单词都是相同长度的,不然是想不到这种方法的……我一开始就没看见……)

具体就是:

单词长度:l,s长度:sl

每次选定一个值为0~l-1的起始指针,初始尾指针与头指针重合,然后每次判断目前指向的那个单词(指针处于这个单词的头部)如果加进目前头尾指针形成的字符串中是否合法,如果合法就把尾指针后移l,否则把头指针移到尾指针后面。

滑动窗口还算是蛮有趣蛮有用的一个思想吧

 1 class Solution {
 2 public:
 3     vector<int>contained, cnt, id;
 4     map<string, int>idx;
 5     int l;
 6     vector<int> findSubstring(string s, vector<string>& words) {
 7         if (s == "" || words.size() == 0)return vector<int>();
 8         vector<int>ans;
 9         contained.resize(words.size());
10         cnt.resize(words.size());
11         id.resize(s.length());
12         sort(words.begin(), words.end());
13         for (int i = 0; i < contained.size(); i++) {
14             contained[i] = 0;
15             cnt[i] = 0;
16             idx.insert(make_pair(words[i], i));
17             cnt[idx[words[i]]]++;
18         }
19         int leng = s.length();
20         l = words[0].size();
21         for (int i = 0; i < leng; i++) {
22             if (idx.find(s.substr(i, l)) != idx.end())
23                 id[i] = idx[s.substr(i, l)];
24             else id[i] = -1;
25         }
26         for (int i = 0; i < l; i++) {
27             int S = i;
28             for (int j = i; j < leng; j += l) {
29                 int now = id[j];
30                 if (now == -1) {
31                     while (S < j) {
32                         contained[id[S]]--;
33                         S += l;
34                     }
35                     S += l;
36                     continue;
37                 }
38                 while (contained[now] >= cnt[now]) {
39                     contained[id[S]]--;
40                     S += l;
41                 }
42                 contained[now]++;
43                 if (j - S + l == l * words.size())
44                     ans.push_back(S);
45             }
46             for (int j = 0; j < contained.size(); j++)
47                 contained[j] = 0;
48         }
49         return ans;
50     }
51 };
View Code
原文地址:https://www.cnblogs.com/yalphait/p/10339505.html