String是字符串列表的排列

时间:2016-11-18 16:20:00

标签: c++

给出了一个单词列表,并给出了一个更大的字符串,给出了如何找到该字符串是否是较小字符串的排列。

eg- s= badactorgoodacting dict[]={'actor','bad','act','good'] FALSE

eg- s= badactorgoodacting dict[]={'actor','bad','acting','good'] TRUE

较小的单词本身不需要置换。问题是我们是否可以找到较小字符串的顺序,这样如果按顺序连接它会给出更大的字符串

还有一个限制 - 来自dict[]的某些字词也可能会遗留在未使用的

以下给出了复杂度O(n2)。有没有其他方法可以做到这一点..以便提高复杂性或提高效率?主要是在Java中。在此先感谢!

bool strPermuteFrom(unordered_set<string> &dict, string &str, int pos)
{
  if(pos >= str.size())

    return true;

  if(dict.size() == 0)
    return false;

  for(int j = pos; j < str.size(); j++){
    string w = str.substr(pos, j - pos + 1);
    if(dict.find(w) != dict.end()){
      dict.erase(w);
      int status = strPermuteFrom(dict, str, j+1);
      dict.insert(w);
      if(status){
        if(pos > 0) str.insert(pos, " ");
        return status;
      }
    }
  }

  return false;
}


bool strPermute(unordered_set<string> &dict, string &str)
{
  return strPermuteFrom(dict, str, 0);
}

1 个答案:

答案 0 :(得分:1)

您提供的代码示例并没有充分利用unordered_set(相当于Java HashSet的属性);每个查找都是O(1),但它必须执行许多查找(对于每个可能的前缀,对于字符串的整个长度)。正在排序的std::set(Java TreeSet)允许您在单个O(log n)查找中找到给定点的所有可能前缀(然后从该点开始扫描,直到您不再处理可能的前缀),而不是在每个递归步骤中查找stringlength O(1)

因此,此代码正在执行O(stringlength * dictsize^2)工作,使用有序集合结构应将其减少到O(dictsize log dictsize)工作。字符串长度无关紧要,因为您不再查找前缀;你在每个递归步骤中查找剩余的字符串一次,并且因为它是有序的,匹配的前缀将在整个字符串之前排序,不需要检查单个子字符串。从技术上讲,回溯仍然是必要的(处理dict中的单词是dict中另一个单词的前缀的情况,例如actacting),但除此之外,你' d永远不需要回溯;对于每个递归步骤,您只需要一次点击,因此您只需要执行dictsize查找,每次查找都会花费log dictsize