LeetCode 30. Substring with Concatenation of All Words

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.

For example, given:
s: "barfoothefoobarman"
words: ["foo", "bar"]

You should return the indices: [0,9].
(order does not matter).

分析

本题是要你找出字符串s中仅包含words中元素的子串,并返回其索引。思路不难想,但要注意一个小细节:words中可能会有多个相同的字符串。
大致思路如下:

  • map1记录words中单词和出现的次数,并按长度分类,把长度放入vector1

  • 从索引0开始到s.size()-1搜索从该索引开始,长度在vector1内的单词是否在map1中出现过,未出现则索引+1,清空记录了当前出现过单词的次数的map2;若出现过再比较其在map2上出现次数是否超出,未超出则在map2相应项+1;

  • 统计允许记载的单词数量是否和words.size()相当,若相等则记录下当前的索引。

具体代码

class Solution {
struct Word {
        int num;
        string value;
        bool operator<(const Word &a) const
        {
            return value < a.value;
        }
        Word(string str,int n):value(str),num(n){}
        Word(string str):value(str),num(1){}
    };
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<int> keys = vector<int>();
        map<int, set<Word>> books = map<int, set<Word>>();
        for (string word : words) {
            if (books.find(word.length()) == books.end()) {
                books[word.length()] = set<Word>();
                keys.push_back(word.length());
                books[word.length()].insert(Word(word));
            }
            else {
                set<Word>::iterator it = books[word.length()].find(Word(word));
                if (it == books[word.length()].end())
                    books[word.length()].insert(Word(word));
                else {
                    int num = (*it).num + 1;
                    books[word.length()].erase(it);
                    books[word.length()].insert(Word(word, num));
                }
            }
        }
        int count = 0;
        vector<int> result = vector<int>();
        map<string, int> scale = map<string, int>();
        int indexFront = 0;
        for (int index = 0; index < s.size(); index++) {
            bool mod = true;
            for (int len : keys) {
                if (len + index > s.size())continue;
                set<Word>::iterator it = books[len].find(Word(s.substr(index, len)));
                if (it == books[len].end())continue;
                else {  
                    if (scale.find(s.substr(index, len)) != scale.end()) {
                        if (scale[s.substr(index, len)] < (*it).num){
                            scale[s.substr(index, len)] = scale[s.substr(index, len)] + 1;
                            count++;
                            index = index + len - 1;
                            mod = false;
                        }
                    }
                    else {
                        scale[(s.substr(index, len))] = 1;
                        index = index + len - 1;
                        mod = false;
                    }
                    break;
                }
            }
            if (mod) {
                count = 0;
                scale.clear();
                index = indexFront;
                indexFront++;
            }
            else if (scale.size() + count == words.size()) {
                count = 0;
                result.push_back(indexFront);
                scale.clear();
                index = indexFront;
                indexFront++;
            }
        }
        return result;
    }
};

事实上还可以采用定长(每个子串的长度为确定的)匹配的方式优化,map也可以换用HashMap(unordered_map)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值