Algorithm:串联所有单词的子串

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

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

示例 1:

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

输入:s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]
输出:[]
示例 3:

输入:s = "barfoofoobarthefoobarman", words = ["bar","foo","the"]
输出:[6,9,12]
 

提示:

1 <= s.length <= 104
s 由小写英文字母组成
1 <= words.length <= 5000
1 <= words[i].length <= 30
words[i] 由小写英文字母组成

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<vector<string>> wordsArr;
        vector<string> wordArr{words[0]}; 
        wordsArr.insert(wordsArr.end(), wordArr);

        for(int i = 1; i < words.size(); i++)
        {
            string word = words[i];

            for(int j = 0; j < wordsArr.size(); j++)
            {
                wordArr = wordsArr[j];
                for(int k = 0; k < wordArr.size(); k++)
                {
                    vector<string> wordArrItem = wordArr;
                    wordArrItem.insert(wordArrItem.begin() + k, word);

                    if(k == 0)
                    {
                        wordsArr[j] = wordArrItem;
                    }
                    else
                    {
                        wordsArr.insert(wordsArr.begin() + j, wordArrItem);
                        j++;
                    }
                }

                wordArr.push_back(word);
                wordsArr.insert(wordsArr.begin() + j, wordArr);
                j++;
            }
        }

        vector<string> composedWordsArr;
        string composedString;
        vector<int> result;

        for(int i = 0; i < wordsArr.size(); i++)
        {
            for(int j = 0; j < wordsArr[i].size(); j++)
            {
                composedString = composedString + wordsArr[i].at(j);
            }

            bool repeated_flag = false;
            for(int k = 0; k < composedWordsArr.size(); k++)
            {
                if(composedWordsArr[k] == composedString)
                {
                    repeated_flag = true;
                    break;
                }
            }

            if(!repeated_flag)
            {
                composedWordsArr.push_back(composedString);
                vector<int> value = strStr(s, composedString);
                result.insert(result.end(), value.begin(), value.end());
            }

            composedString = "";
        }

        return result;
    }

private:
    vector<int> strStr(string haystack, string needle) {
        int needle_size = needle.size();
        vector<int> result;

        if(needle_size == 0)
            return result;

        int haystack_size = haystack.size();

        if(haystack_size < needle_size)
            return result;

        for(int i = 0; i <= haystack_size - needle_size; i++)
        {
            string haystack_sub = haystack.substr(i, needle_size);
            if(haystack_sub == needle)
                result.push_back(i);
        }

        return result;
    }
};

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Solution {

	struct strWordCounter
	{
		string word;
		int counter;
	};

	struct strWordsCounter
	{
		string word;
		vector<strWordCounter> counters;
	};

public:
	vector<int> findSubstring(string s, vector<string>& words) {
		vector<string> wordArr;
		vector<strWordsCounter> wordsCounter;
		vector<strWordCounter> wordCounter;
		vector<int> result;

		for (int i = 0; i < words.size(); i++)
		{
			bool isFind = false;
			for (int j = 0; j < wordCounter.size(); j++)
			{
				if (wordCounter[j].word == words[i])
				{
					isFind = true;
					wordCounter[j].counter++;
					break;
				}
			}

			if (!isFind)
			{
				strWordCounter tempCounter{words[i], 1};
				wordCounter.push_back(tempCounter);
			}
		}
#if 1
		for (int i = 0; i < wordCounter.size(); i++)
		{
			cout << "wordCounter[" << i << "] word = " << wordCounter.at(i).word.c_str()  << " counter = " << wordCounter.at(i).counter << endl;
		}
#endif
		vector<strWordCounter> tempWordCounter = wordCounter;

		for (int i = 0; i < wordCounter.size(); i++)
		{
			//cout << "wordCounter[" << i << "] word = " << wordCounter.at(i).word.c_str() << " counter = " << wordCounter.at(i).counter << endl;

			if (wordCounter[i].counter <= 1)
			{
				tempWordCounter.erase(tempWordCounter.begin() + i);
			}
			else
			{
				tempWordCounter[i].counter--;
			}

			wordsCounter.push_back({ wordCounter[i].word, tempWordCounter});
			tempWordCounter = wordCounter;
		}
# if 1
		for (int i = 0; i < wordsCounter.size(); i++)
		{
			cout << "wordsCounter[" << i << "] word = " << wordsCounter.at(i).word.c_str() << endl;

			for (int j = 0; j < wordsCounter[i].counters.size(); j++)
			{
				cout << "wordCounter[" << i << "].counters[" << j << "] word = " << wordsCounter[i].counters.at(j).word.c_str() << " counter = " << wordsCounter[i].counters.at(j).counter << endl;
			}
		}
#endif
		for (int i = 0; i < wordsCounter.size(); )
		{
			string tempWord = wordsCounter[i].word;
			wordCounter = wordsCounter[i].counters;
			wordsCounter.erase(wordsCounter.begin() + i);

#if 1
			cout << "i = " << i << " tempWord = " << tempWord.c_str() << endl;
			for (int j = 0; j < wordCounter.size(); j++)
			{
				cout << "wordCounter[" << j << "] word = " << wordCounter.at(j).word.c_str() << " counter = " << wordCounter.at(j).counter << endl;
			}
#endif
			if (wordCounter.empty())
			{
				wordArr.push_back(tempWord);
				//cout << "tempWord = " << tempWord.c_str() << endl;
				continue;
			}

			tempWordCounter = wordCounter;
			for (int j = 0; j < wordCounter.size(); j++)
			{
				string temString = tempWord + wordCounter[j].word;
				//cout << "j = " << j << " temString = " << temString.c_str() << endl;

				if (wordCounter[j].counter <= 1)
				{
					tempWordCounter.erase(tempWordCounter.begin() + j);
					//cout << "tempWordCounter erase at" << j << endl;
				}
				else
				{
					tempWordCounter[j].counter--;
					//cout << "tempWordCounter at " << j << " counter = " << tempWordCounter[j].counter << endl;
				}

				wordsCounter.push_back({ temString, tempWordCounter });
				tempWordCounter = wordCounter;
			}
		}

		for (int i = 0; i < wordArr.size(); i++)
		{
			cout << "wordArr[" << i << "] = " << wordArr.at(i).c_str() << endl;
			vector<int> value = strStr(s, wordArr.at(i));
			result.insert(result.end(), value.begin(), value.end());
		}

		return result;
	}

private:
	vector<int> strStr(string haystack, string needle) {
		int needle_size = needle.size();
		vector<int> result;

		if (needle_size == 0)
			return result;

		int haystack_size = haystack.size();

		if (haystack_size < needle_size)
			return result;

		for (int i = 0; i <= haystack_size - needle_size; i++)
		{
			string haystack_sub = haystack.substr(i, needle_size);
			if (haystack_sub == needle)
				result.push_back(i);
		}

		return result;
	}
};

int main()
{
	Solution obj;
	vector<string> words{ "dhvf","sind","ffsl","yekr","zwzq","kpeo","cila","tfty","modg","ztjg","ybty","heqg","cpwo","gdcj","lnle","sefg","vimw","bxcb" };

	vector<int> result = obj.findSubstring("pjzkrkevzztxductzzxmxsvwjkxpvukmfjywwetvfnujhweiybwvvsrfequzkhossmootkmyxgjgfordrpapjuunmqnxxdrqrfgkrsjqbszgiqlcfnrpjlcwdrvbumtotzylshdvccdmsqoadfrpsvnwpizlwszrtyclhgilklydbmfhuywotjmktnwrfvizvnmfvvqfiokkdprznnnjycttprkxpuykhmpchiksyucbmtabiqkisgbhxngmhezrrqvayfsxauampdpxtafniiwfvdufhtwajrbkxtjzqjnfocdhekumttuqwovfjrgulhekcpjszyynadxhnttgmnxkduqmmyhzfnjhducesctufqbumxbamalqudeibljgbspeotkgvddcwgxidaiqcvgwykhbysjzlzfbupkqunuqtraxrlptivshhbihtsigtpipguhbhctcvubnhqipncyxfjebdnjyetnlnvmuxhzsdahkrscewabejifmxombiamxvauuitoltyymsarqcuuoezcbqpdaprxmsrickwpgwpsoplhugbikbkotzrtqkscekkgwjycfnvwfgdzogjzjvpcvixnsqsxacfwndzvrwrycwxrcismdhqapoojegggkocyrdtkzmiekhxoppctytvphjynrhtcvxcobxbcjjivtfjiwmduhzjokkbctweqtigwfhzorjlkpuuliaipbtfldinyetoybvugevwvhhhweejogrghllsouipabfafcxnhukcbtmxzshoyyufjhzadhrelweszbfgwpkzlwxkogyogutscvuhcllphshivnoteztpxsaoaacgxyaztuixhunrowzljqfqrahosheukhahhbiaxqzfmmwcjxountkevsvpbzjnilwpoermxrtlfroqoclexxisrdhvfsindffslyekrzwzqkpeocilatftymodgztjgybtyheqgcpwogdcjlnlesefgvimwbxcbzvaibspdjnrpqtyeilkcspknyylbwndvkffmzuriilxagyerjptbgeqgebiaqnvdubrtxibhvakcyotkfonmseszhczapxdlauexehhaireihxsplgdgmxfvaevrbadbwjbdrkfbbjjkgcztkcbwagtcnrtqryuqixtzhaakjlurnumzyovawrcjiwabuwretmdamfkxrgqgcdgbrdbnugzecbgyxxdqmisaqcyjkqrntxqmdrczxbebemcblftxplafnyoxqimkhcykwamvdsxjezkpgdpvopddptdfbprjustquhlazkjfluxrzopqdstulybnqvyknrchbphcarknnhhovweaqawdyxsqsqahkepluypwrzjegqtdoxfgzdkydeoxvrfhxusrujnmjzqrrlxglcmkiykldbiasnhrjbjekystzilrwkzhontwmehrfsrzfaqrbbxncphbzuuxeteshyrveamjsfiaharkcqxefghgceeixkdgkuboupxnwhnfigpkwnqdvzlydpidcljmflbccarbiegsmweklwngvygbqpescpeichmfidgsjmkvkofvkuehsmkkbocgejoiqcnafvuokelwuqsgkyoekaroptuvekfvmtxtqshcwsztkrzwrpabqrrhnlerxjojemcxel", words);

	for (int i = 0; i < result.size(); i++)
	{
		cout << result[i] << " ";
	}

	cout << endl;

	return 0;
}

现在处理时间还是太长,需要继续改进。在处理过程中,如果一个string不能找到,就直接删除。 

class Solution {

	struct strWordCounter
	{
		string word;
		int counter;
	};

	struct strWordsCounter
	{
		string word;
		vector<strWordCounter> counters;
	};

public:
	vector<int> findSubstring(string s, vector<string>& words) {
		vector<string> wordArr;
		vector<strWordsCounter> wordsCounter;
		vector<strWordCounter> wordCounter;
		vector<int> result;
		int wordSize = 0;

		for (int i = 0; i < words.size(); i++)
		{
			bool isFind = false;
			wordSize += words[i].size();

			for (int j = 0; j < wordCounter.size(); j++)
			{
				if (wordCounter[j].word == words[i])
				{
					isFind = true;
					wordCounter[j].counter++;
					break;
				}
			}

			if (!isFind)
			{
				strWordCounter tempCounter{words[i], 1};
				wordCounter.push_back(tempCounter);
			}
		}

		for (int i = 0; i < wordCounter.size(); i++)
		{
			if (!strHasEnoughWordCounter(s, wordCounter.at(i).word, wordCounter.at(i).counter, 0))
			{
				return result;
			}
		}

		vector<strWordCounter> tempWordCounter = wordCounter;

		for (int i = 0; i < wordCounter.size(); i++)
		{
			if (wordCounter[i].counter <= 1)
			{
				tempWordCounter.erase(tempWordCounter.begin() + i);
			}
			else
			{
				tempWordCounter[i].counter--;
			}

			wordsCounter.push_back({ wordCounter[i].word, tempWordCounter});
			tempWordCounter = wordCounter;
		}

		for (int i = 0; i < wordsCounter.size(); )
		{
			string tempWord = wordsCounter[i].word;
			wordCounter = wordsCounter[i].counters;
			wordsCounter.erase(wordsCounter.begin() + i);

			if (wordCounter.empty())
			{
				wordArr.push_back(tempWord);
				continue;
			}

			tempWordCounter = wordCounter;
			for (int j = 0; j < wordCounter.size(); j++)
			{
				string temString = tempWord + wordCounter[j].word;
				if (strHasEnoughWordCounter(s, temString, 1, wordSize - temString.size()))
				{
					if (wordCounter[j].counter <= 1)
					{
						tempWordCounter.erase(tempWordCounter.begin() + j);
					}
					else
					{
						tempWordCounter[j].counter--;
					}

					wordsCounter.push_back({ temString, tempWordCounter });
					tempWordCounter = wordCounter;
				}
			}
		}

		for (int i = 0; i < wordArr.size(); i++)
		{
			vector<int> value = strStr(s, wordArr.at(i), 0);
			result.insert(result.end(), value.begin(), value.end());
		}

		return result;
	}

private:
	bool strHasEnoughWordCounter(string haystack, string needle, int counter, int offset) {
		int needle_size = needle.size();
		int tmpCounter = 0;

		if (needle_size == 0)
			return true;

		int haystack_size = haystack.size();

		if (haystack_size < needle_size)
			return false;

		for (int i = 0; i <= haystack_size - needle_size - offset; i++)
		{
			string haystack_sub = haystack.substr(i, needle_size);
			if (haystack_sub == needle)
				tmpCounter++;
			if (tmpCounter >= counter)
				return true;
		}

		return false;
	}

	vector<int> strStr(string haystack, string needle, int offset) {
		int needle_size = needle.size();
		vector<int> result;

		if (needle_size == 0)
			return result;

		int haystack_size = haystack.size();

		if (haystack_size < needle_size)
			return result;

		for (int i = 0; i <= haystack_size - needle_size - offset; i++)
		{
			string haystack_sub = haystack.substr(i, needle_size);
			if (haystack_sub == needle)
				result.push_back(i);
		}

		return result;
	}
};

#include <map>

class Solution {

public:
	vector<int> findSubstring(string s, vector<string>& words) {
		vector<int> result;
		int wordSize = 0;
		int sSize = s.size();
		map<char, int> wordsCharTable; // 记录words a~z的数目
		map<char, int> sCharTable; // 记录当前i位置处子字符串 a~z的数目
		vector<string> correctStringVec; // 记录字母数目相同,正确的String
		vector<string> wronStringVec; // 记录字母数目相同,错误的String

		for (char i = 'a'; i <= 'z'; i++)
		{
			wordsCharTable[i] = 0;
			sCharTable[i] = 0;
		}

		for (int i = 0; i < words.size(); i++)
		{
			wordSize += words[i].size();
			for (int j = 0; j < words[i].size(); j++)
			{
				wordsCharTable[words[i][j]]++;
			}
		}

		int sWordLen = sSize - wordSize;

		if (sWordLen < 0)
		{
			return result;
		}

		for (int i = 0; i < wordSize; i++)
		{
			sCharTable[s[i]]++;
		}

		for (int i = 0; i <= sWordLen; i++)
		{
            // 尽量在第一个for循环下面多做判断
			if (i != 0)
			{
				sCharTable[s[i - 1]]--;
				sCharTable[s[i + wordSize - 1]]++;
			}

			if (wordsCharTable != sCharTable)
			{
				continue;
			}
			else
			{
				string wholeContxt = s.substr(i, wordSize);
				bool inCcorrectStringVec = false;
				for (auto const& strObj : correctStringVec)
				{
					if (strObj == wholeContxt)
					{
						inCcorrectStringVec = true;
						break;
					}
				}

				if (inCcorrectStringVec)
				{
					result.push_back(i);
					continue;
				}
				else
				{
					bool inWronStringVec = false;
					for (auto const& strObj : wronStringVec)
					{
						if (strObj == wholeContxt)
						{
							inWronStringVec = true;
							break;
						}
					}

					if (inWronStringVec)
					{
						continue;
					}
				}
			}

			vector<string> tmpWords = words;
			for (int j = i; j < i + wordSize; )
			{
				bool isFind = false;
				for (int k = 0; k < tmpWords.size(); k++)
				{
					string s_sub = s.substr(j, tmpWords[k].size());
					if (s_sub == tmpWords[k])
					{
						j += s_sub.size();
						tmpWords.erase(tmpWords.begin() + k);
						isFind = true;
						break;
					}
				}
				if (!isFind)
				{
					break;
				}
			}

			if (tmpWords.empty())
			{
				result.push_back(i);
				correctStringVec.push_back(s.substr(i, wordSize));
			}
			else
			{
				wronStringVec.push_back(s.substr(i, wordSize));
			}
		}

		return result;
	}
};

 

  

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AllenSun-1990

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值