1. 程式人生 > 實用技巧 >70串聯所有單詞的子串(30)

70串聯所有單詞的子串(30)

作者: Turbo時間限制: 1S章節: 雜湊表

晚於: 2020-08-19 12:00:00後提交分數乘係數50%

截止日期: 2020-08-26 12:00:00

問題描述 :

給定一個字串 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.

輸入範例 :

輸出範例 :

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
using namespace std;

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) 
    {
        vector<int> res;
        if(!words.size())
            return res;
        int single=words[0].length();
        int num=words.size();
        
        unordered_map<string,int> map1;
        
        for(const auto& t:words)
            map1[t]++;//設定目標map
        for(int start=0;start<single;start++)//設定不同的起點 
        {
            int left=start,right=start,count=0;
            unordered_map<string,int> map2;//當前的map
            while(right+single<=s.size())
            {
                string str=s.substr(right,single);//擷取一個單詞
                right+=single;//移動右邊界
                if(map1.find(str)==map1.end())//若當前單詞不在target中 則重置
                {
                    count=0;
                    map2.clear();
                    left=right;
                }
                else
                {
                    map2[str]++;
                    count++;
                    //為什麼是while呢
                    //因為左邊第一個單詞不一定是str
                    while(map1[str]<map2[str])//若當前str的次數大於target中str的次數 則左移
                    {
                        string temp=s.substr(left,single);
                        map2[temp]--;
                        left+=single;
                        count--;
                    }
                    if(count==num)res.push_back(left);
                }
            }
        }
        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;
}