赞
踩
给定一个源字符串 s,再给一个字符串数组,要求在源字符串中找到由字符串数组各种组合组成的连续串的起始下标,如果存在多个,在结果中都需要输出。
这一题看似很难,但是有 2 个限定条件也导致这题不是特别难。1. 字符串数组里面的字符串长度都是一样的。2. 要求字符串数组中的字符串都要连续连在一起的,前后顺序可以是任意排列组合。
解题思路,先将字符串数组里面的所有字符串都存到 map 中,并累计出现的次数。然后从源字符串从头开始扫,每次判断字符串数组里面的字符串时候全部都用完了(计数是否为 0),如果全部都用完了,并且长度正好是字符串数组任意排列组合的总长度,就记录下这个组合的起始下标。如果不符合,就继续考察源字符串的下一个字符,直到扫完整个源字符串。
#include <iostream> #include <vector> #include <string> #include <map> using namespace std; vector<int> findSubstring(string S, vector<string> &L) { vector<int> result; if (S.size() <= 0 || L.size() <= 0) { return result; } int n = S.size(), m = L.size(), l = L[0].size(); //将所有单词放入map中 map<string, int>expected; for (int i = 0; i < m; i++) { if (expected.find(L[i]) != expected.end()) { expected[L[i]]++; } else { expected[L[i]] = 1; } } for (int i = 0; i < l; i++) { map<string, int>actual; int count = 0;//总数 int winLeft = i; for (int j = i; j <= n - 1; j += l) { string word = S.substr(j, l); //如果没有找到,则从j+1重新开始; if (expected.find(word) == expected.end()) { actual.clear(); count = 0; winLeft = j + l; continue; } count++; //计算“单词”的数量 if (actual[word] > expected[word]) { string tmp; do { count--; actual[tmp]--; winLeft += l; } while (tmp != word); } // 如果总计数等于 L 的大小,则找到一个结果 if (count == m) { result.push_back(winLeft); string tmp = S.substr(winLeft, l); actual[tmp]--; winLeft += l; count--; } } } return result; } int main(int argc, char **argv) { string s = "barfoobarfoothefoobarman"; vector<string> l; l.push_back("foo"); l.push_back("bar"); l.push_back("foo"); vector<int> indics = findSubstring(s, l); for (int i = 0; i < indics.size(); i++) { cout << indics[i] << "."; } cout << endl; return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。