串联所有单词的子串

问题描述

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

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

示例 1:

输入:

  s = "barfoothefoobarman",

  words = ["foo","bar"]

输出:0 9

解释:

从索引 0 和 9 开始的子串分别是 "barfoo" 和 "foobar" 。输出时,按照索引由小到大顺序输出。

示例 2:

输入:

  s = "wordgoodgoodgoodbestword",

  words = ["word","good","best","word"]

输出:-1

s中的子串无法由words串联得到,所以输出-1

可使用以下main函数:

int main()

{

    string s,str;

    vector<string> words;

    int n;

    cin>>s;

    cin>>n;

    for(int i=0; i<n; i++)

    {

        cin>>str;

        words.push_back(str);

    }

    vector<int> res=Solution().findSubstring(s, words);

    if (res.size()> 0)

        for(int i=0; i<res.size(); i++)

        {

            if (i> 0)

                cout<<" ";

            cout<<res[i];

        }

    else

        cout<<-1;

    return 0;

}

输入说明

首先收入字符串s,

然后输入words中单词的数目n,

最后输入n个字符串,表示words中的单词

输出说明

按照索引由小到大顺序输出,或者输出-1.

输入范例

barfoothefoobarman
2
foo bar

输出范例

0 9

实现思路

思路与判断是否为字母异位词一样,只不过本题是判断单词是否异位。(但本代码对那个巨长的a字符串会运行超时)

实现代码
#include <iostream>

#include<sstream>

#include <vector>

#include<math.h>

#include<unordered_map>

using namespace std;


class Solution {
public:

    bool isAnagram(vector<string>&a,vector<string>&b){
        unordered_map<string,int>mp;
        for(int i = 0;i<a.size();i++){
            mp[a[i]]++;
        }

        for(int i = 0;i<b.size();i++){
            mp[b[i]]--;
        }

        for(std::unordered_map<string,int>::iterator it = mp.begin();it!=mp.end();++it){
            if(it->second!=0) return false;
        }
        return true;
    }

    vector<int> findSubstring(string s, vector<string>& words) {
        vector<string> str;
        vector<int>res;
        /*for(int i = 0;i<words.size();i++){
            str += words[i];
        }*/
        int n = words.size()*words[0].size();//words所有单词的长度

        for(int i = 0;i<s.size()-n+1;i++){
            string tem = "";
            for(int j = i;j<i+n;j++){
                tem += s[j];
                if(tem.size()==words[0].size()){
                    str.push_back(tem);
                    tem = "";
                }
            }
            if(isAnagram(words,str)) res.push_back(i);
            str.clear();//要记得清空上一次获得的字符串
        }

        return res;
    }
};

int main()

{

    string s,str;

    vector<string> words;

    int n;

    cin>>s;

    cin>>n;

    for(int i=0; i<n; i++)

    {

        cin>>str;

        words.push_back(str);

    }

    vector<int> res=Solution().findSubstring(s, words);

    if (res.size()> 0)

        for(int i=0; i<res.size(); i++)

        {

            if (i> 0)

                cout<<" ";

            cout<<res[i];

        }

    else

        cout<<-1;



    return 0;

}

### 使用滑动窗口算法解决串联所有单词子串 #### 解决方案概述 为了处理 LeetCode 第 30 题的要求,即在字符串 `s` 中寻找由字符串数组 `words` 组成的所有可能的连续子串的位置,采用滑动窗口方法是一种高效的选择[^1]。 #### 参数定义与初始化 设定了几个重要的参数来辅助解决问题: - 设 `m = words.length` 表示单词的数量; - 设 `len` 是 `words` 数组中单个单词的长度,则整个窗口宽度应设定为 `len * m`;这代表了当我们在字符串 `s` 上应用此窗口时所期望匹配到的一系列连续字符总长度[^2]。 #### 实现思路 通过内外两层嵌套的方式实现滑动窗口机制: 外层循环负责遍历起点位置的变化,每次前进步长设置为单一单词长度(`len`)。对于每一个新的起始点而言, 内层则利用固定大小等于全部目标短语拼接后的整体尺寸(`len*m`)作为扫描单位,在当前选定范围内逐一对比是否存在符合条件的结果集[^4]。 具体操作如下所示: ```python from collections import Counter, defaultdict def findSubstring(s: str, words: List[str]) -> List[int]: if not s or not words: return [] word_length = len(words[0]) total_words = len(words) window_size = word_length * total_words # 记录每个单词出现次数 word_count = Counter(words) result_indices = [] for i in range(word_length): start = i current_word_counts = defaultdict(int) matched_words = 0 for j in range(i, len(s) - word_length + 1, word_length): substring = s[j:j + word_length] if substring in word_count: current_word_counts[substring] += 1 while current_word_counts[substring] > word_count[substring]: temp_start_str = s[start:start + word_length] current_word_counts[temp_start_str] -= 1 if current_word_counts[temp_start_str] >= word_count[temp_start_str]: matched_words -= 1 start += word_length matched_words += 1 if matched_words == total_words: result_indices.append(start) else: start = j + word_length current_word_counts.clear() matched_words = 0 return result_indices ``` 该函数首先检查输入的有效性并计算必要的变量值。接着创建了一个外部for循环用于控制初始偏移量i (范围是从0至word_length),从而确保能够捕捉到任何潜在解法而不遗漏任何一个可能性。内部逻辑则是基于上述提到的方法论构建而成,旨在有效地定位满足条件的索引列表。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值