LeetCode:30. Substring with Concatenation of All Words

这道题并不是很难(虽然没有做出来),让我感到惊讶的是oj竟然接受了一个看上去这么耗时的方法。

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        if (words.empty())
            return vector<int>();
        unordered_map<string, int> cnts;
        for (auto& str : words)
            cnts[str]++;
        int len = words[0].size(), sz = words.size();
        vector<int> ret;
        for (int i = 0; i < s.size() - len * sz + 1; ++i) {
            unordered_map<string, int> seen;
            int k;
            for (k = 0; k < sz; ++k) {
                string ss = s.substr(i+k*len, len);
                if (find(words.begin(), words.end(), ss) != words.end()) {
                    ++seen[ss];
                    if (seen[ss] > cnts[ss])
                        break;
                } else
                    break;
            }
            if (k == sz)
                ret.push_back(i);
        }
        return ret;
    }
};

在我眼中,循环每次创造一个map,截取很多子串,然后find,这样都是很耗时的操作,但是没想到竟然就是这么笨的方法过了。

其实来说,这一题看上去,就是一个很耗时的题目,基本上是每个位置都要检查的。所以下次不要觉得自己方法笨就不去试一下了

ok,其实是有优化的方法的。
每次移动一个单词的长度,就可以使用滑动窗口了。

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        unordered_map<string, int> dict;
        for (auto& word : words)
            dict[word]++;
        int sz = words.size();
        if (sz == 0)
            return vector<int>();
        int wordSz = words[0].size();
        vector<int> res;
        for (int i = 0; i < wordSz; ++i) {
            unordered_map<string, int> window;
            int cnt = 0;
            for (int j = i; j < s.size()-wordSz+1; j += wordSz) {
                if (j >= i+wordSz*sz) {
                    string str = s.substr(j-wordSz*sz, wordSz);
                    if (dict.find(str) != dict.end()) {
                        --window[str];
                        if (window[str] < dict[str])
                            --cnt;
                    }
                }
                string str = s.substr(j, wordSz);
                if (dict.find(str) != dict.end()) {
                    window[str]++;
                    if (window[str] <= dict[str])
                        ++cnt;
                    if (cnt == sz)
                        res.push_back(j - (sz-1)*wordSz);
                }
            }
        }
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值