leetcode#30. Substring with Concatenation of All Words

给定一个字符串 s 和一些长度相同的单词 words。在 s 中找出可以恰好串联 words 中所有单词的子串的起始位置。

注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。

示例 1:

输入:
  s = "barfoothefoobarman", words = ["foo","bar"] 输出: [0,9] 解释: 从索引 0 和 9 开始的子串分别是 "barfoo" 和 "foobar" 。 输出的顺序不重要, [9,0] 也是有效答案。 
示例 2:

输入:
  s = "wordgoodstudentgoodword", words = ["word","student"] 输出: [] 

//题目好像有问题,说的是长度相等,但是用例给的却不一样。
//如果一样,那么我们每次扫描word.size()个字符

太难了,只能看别人的代码了。

思路是这样。

对于例子1,我们可以把它分成bar,foo,the,foo,bar,man或者arf,oot,hef,oob,arm或者rfo,oth,efo,oba,rman

//我们来模拟一下:barfoothefoobarman。设想一下我们现在有个滑动窗口,大小为6=total*word[0].size(),进入一个则

//先从索引0开始匹配。最初的时候。我们需要匹配2个字符bar和foo。cnt=2,需要匹配两者数量各1个。(数量就是你需要匹配的个数)

//第一个子串bar匹配,还需要匹配1个foo。bar的数量0,foo数量1

//foo匹配,还需匹配0个,放入结果。bar 0 ,foo 0

//the,bar滑出窗口(需要+1),the -1,foo 0,bar 1。(因为它前面是foo)

//foo出,foo入,the -1,foo 0,bar 1,

//bar入,the出, the 0,foo 0,bar 0。放入结果

两个结果都得到了。也就是说字符串str进入,数量就-1,那么只有当bar和foo同时进入的时候,cnt才为0.

而类似barfoogfoobar这样种情况,只是滑动窗口的起点不一样。

那么,我们需要一个cnt来检视数量。

新加入的字符串数量减1,表示我们需要的数量减1,数量大于0,如果在减少之前,字符串数量大于0(也就是我们需要匹配的字符出现了),cnt减少。

而滑出的字符串,我们先把数量+1,如果这个数大于0,cnt加1。因为如果这个字符串不是我们关心的,它其实没有机会大于0.

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        if(s==""||words.size()==0) return {};
        int n = s.size(), len = words[0].size(), total = words.size(), cnt = total;
        vector<int> res;
        unordered_map<string, int> counts;
        for (string str : words) 
      counts[str]++; for (int i = 0; i < len; i++) {//比如"oooooooooooo" "ooo" "ooo",需要每个子串都从内部走len个长度。为什么不能>=len呢?会重复。 unordered_map<string, int> wordcnt = counts; cnt = total; for (int j = i; j + len <= n; j += len) {// string cur = s.substr(j, len); if (wordcnt[cur]-- > 0) cnt--; if (j - total*len >= 0) { string out = s.substr(j - total*len, len); // the word out side of current sliding window if (++wordcnt[out] > 0) cnt++; } if (cnt == 0) res.push_back(j - (total-1)*len); } } return res; } };

 

转载于:https://www.cnblogs.com/lsaejn/p/9723757.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值