Substring with Concatenation of All Words

本文介绍了一种寻找字符串中由给定单词列表组成的子串的方法。通过两种思路实现:一是逐个检查子串并使用标记记录状态;二是利用哈希表统计单词出现次数,提高效率。适用于需要在文本中快速定位特定组合的应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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: []

思路一:

1.把每一个子串送给一个判别函数进行判断,同时用vector<bool>去标记每一个words的受访问状态,也即在一次外层判断中,一个子串只能访问words的单词一次。

2.终止条件,如果剩余的子串长度小于words中字符串总长度,则一定找不到了,停止查找

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        if(words.empty()||s.empty())
            return {};
        int wsz=words.size();
        int cnt=0;
        vector<int> result;
        for(int j=0;j<=int(s.size())-int(words[0].size())*wsz;j++)
        {
            vector<bool> state(wsz,true);
            for(int i=0;i<words[0].size()*wsz;)//终止条件
            {
                bool flag=inWords(s.substr(j+i,words[0].size()),words,state);//判断子串
                if(flag)
                {
                    cnt++;//统计匹配次数
                    if(cnt==wsz)//words所有单词都已成功匹配
                    {
                        cnt=0;
                        result.push_back(j);//记录索引
                        break;
                    }
                    i=i+words[0].size();//判断下一个同等长度的单词是否出现在words中
                }
                else {
                    cnt = 0;//如果存在一个匹配不上,则统计清零,重新开始
                    break;
                }
            }
        }
        return result;
    }
    //判断子串是否存在words中,用state来统计受匹配次数,不能重复匹配
    bool inWords(string s,vector<string>& words,vector<bool>& state)
    {
        for(int i=0;i<words.size();i++)
        {
            if(words[i]==s&&state[i])
            {
                state[i]=false;
                return true;
            }
        }
        return false;
    }
};

思路简单,但是时间复杂度太高,而且没有考虑到words内单词重复的情况,用哈希表既可以统一考虑单词重复的情形,也可以免除vector<bool>统计状态带来的麻烦:

思路二:用哈希表存储单词及其被允许匹配的次数

class Solution {
public:
     vector<int> findSubstring(string s, vector<string>& words) {
         vector<int> result;
         if (s.empty()||words.empty()) 
             return result;
         int m = words.size(), n = words[0].size();
         unordered_map<string,int> map1;//存储word及其次数
         for(auto& w:words)
             ++map1[w];
         for(int i=0;i<=int(s.size())-m*n;i++)
         {
             unordered_map<string,int> map2;
             int j=0;
             for(;j<m;j++)
             {
                 string str=s.substr(i+j*n,n);
                 if(map1.find(str)==map1.end())
                     break;//没找到
                 ++map2[str];//匹配成功
                 if(map2[str]>map1[str])//超过匹配次数
                     break;
             }
             if(j==m) 
                 result.push_back(i);
         }
         return result;
     }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值