Shortest substring containing three short strings

来源:互联网 发布:2017怎么申请开淘宝店 编辑:程序博客网 时间:2024/06/03 12:28

@(leetcode)[字符串, Google]

Problem

Given a long string s and short strings t1, t2, t3 (which can have different length) find the shortest substring of s which contains t1, t2 and t3.

Example:
s = "abcdefghijklmnopqrst", t1 = "abc", t2 = "cde", t3 = "klmn", return "abcdefghijklmn";

Solution

我们可以得到一个时间负责O(N),空间复杂度为O(1)的算法,因为题目中告知t1, t2, t3是short strings.具体的算法流程如下:1.初始化,len为t的长度,len1-3分别为s1-3的长度,min_len=min(len1,len2,len3), max_len=max(len1, len2, len3),以及扫描的起始位置idx,s1-3找到匹配时候的索引idx1-3 2.从idx开始,查看是否找到s1的匹配,如果找到更新idx1的位置,并且判断idx1,idx2,idx3是否都大于0,如果是,则可以根据这三个位置以及他们各自的长度求出当前包含它们的最小子字符串。并更新结果。3.同理,依次检查s2, s3是否找到匹配,如果找到就进行与步骤2一样的处理。4.做一点小的优化,如果在某次循环中得出的子字符串长度已经等于max_len,那么就没有比较继续搜索,此时的子字符串就是结果。

Code

#include <iostream>#include <string>#include <utility>#include <cstring>#include <algorithm>#include <cassert>using namespace std;typedef pair<int, int> sub_string;int cal_end_idx(sub_string const &str) {  return str.first + str.second;}//计算此时包含三个字符串的最小子字符串void cal_shortest_sub_str(int idx1, int idx2, int idx3, size_t len1,                          size_t len2, size_t len3, sub_string& res) {  if(idx1 < 0 || idx2 < 0 || idx3 < 0) {    return;  }  size_t start_idx = min(min(idx1, idx2), idx3);  size_t end_idx = max(max(idx1 + len1, idx2 + len2), idx3 + len3);  int tmp_sub_len = (end_idx - start_idx);  if(tmp_sub_len < res.second) {    res.first = start_idx;    res.second = tmp_sub_len;  }}string find_shortest_sub_string(const string &s, const string &s1, const string &s2, const string &s3) {  if(s.empty() || s1.empty() || s2.empty() || s3.empty()) {    return "";  }  size_t len = s.size(), len1 = s1.size(), len2 = s2.size(), len3 = s3.size();  size_t max_len = max(max(len1, len2), len3);  size_t min_len = min(min(len1, len2), len3);  const char* s_str = s.c_str(), *s1_str = s1.c_str(), *s2_str = s2.c_str(), *s3_str = s3.c_str();  int idx1 = -1, idx2 = -1, idx3 = -1;  sub_string result = make_pair(0, len);  for(int idx = 0; (idx + min_len) < len; ++idx) {    if(0 == strncmp(s_str + idx, s1_str, len1)) {      idx1 = idx;      cal_shortest_sub_str(idx1, idx2, idx3, len1, len2, len3, result);    }    if(0 == strncmp(s_str + idx, s2_str, len2)) {      idx2 = idx;      cal_shortest_sub_str(idx1, idx2, idx3, len1, len2, len3, result);    }    if(0 == strncmp(s_str + idx, s3_str, len3)) {      idx3 = idx;      cal_shortest_sub_str(idx1, idx2, idx3, len1, len2, len3, result);    }    //如果此时子字符串的长度已经是max_len,已经找到结果,直接跳出循环    if(result.second == max_len) {      break;    }  }  if(idx1 < 0 || idx2 < 0 || idx3 < 0) {    return "";  }  return s.substr(result.first, result.second);}void Test(){    {        const std::string input("abc0123456789aksdfjasd");        const std::string s1("0123");        const std::string s2("3456");        const std::string s3("");        std::string result = find_shortest_sub_string(input, s1, s2, s3);        cout << "cal : " << result << " answer : " <<  "empty" << endl;        assert(result.empty() == true);    }    {        const std::string input("abc0123456789aksdfjasd");        const std::string s1("0123456");        const std::string s2("3456");        const std::string s3("1234");        std::string result = find_shortest_sub_string(input, s1, s2, s3);        cout << "cal : " << result << " answer : " << "0123456" << endl;        assert(result == std::string("0123456"));    }    {        const std::string input("abc0123456789aksdfjasd");        const std::string s1("0123");        const std::string s2("3456");        const std::string s3("6789");        std::string result = find_shortest_sub_string(input, s1, s2, s3);        cout << "cal : " << result << " answer : " << "0123456789" << endl;        assert(result == std::string("0123456789"));    }    {        const std::string input("sdfa01234ad23456dfad6789abc0123456789aksdfjasd");        const std::string s1("0123");        const std::string s2("3456");        const std::string s3("6789");        std::string result = find_shortest_sub_string(input, s1, s2, s3);        cout << "cal : " << result << " answer : " << "0123456789" << endl;        assert(result == std::string("0123456789"));    }    {        const std::string input(               "sdfa01234ad23456dfad6789abc0123456789aksdfjasd0123skd3456kjsd6789jhs");        const std::string s1("0123");        const std::string s2("3456");        const std::string s3("6789");        std::string result = find_shortest_sub_string(input, s1, s2, s3);        cout << "cal : " << result << " answer : " << "0123456789" << endl;        assert(result == std::string("0123456789"));    }}int main() {  Test();}
0 0
原创粉丝点击