【问题标题】:All possible sequences within the number of length N with given condition给定条件下长度为 N 的所有可能序列
【发布时间】:2014-12-25 18:03:41
【问题描述】:

例如,我们得到长度为 5 (n = 5) 的字符串“Number”,它由从 1 到 a 的所有数字组成(数字可以重复,但从 1 到 a 的所有数字都必须包含在字符串中,并且字符串必须长度为 n)。假设 a = 2 并生成具有先前给定条件的示例性数字(或者更确切地说是数字序列),让它成为“12211”,长度为 5,由 1 和 2 组成。现在假设我们需要找到一种算法,该算法将在我们的字符串“Number”中找到所有可能的数字序列,其中每个序列都是“Number”的子字符串,每个序列都有不同的长度,可能只包含一次出现的任何数字。

对于我们的示例“12211”,我们可以说有 7 个序列:

1.    "1"
2.    "12"
3.    "2"
4.    "2"
5.    "21"
6.    "1"
7.    "1"

结果将是“7”。

为清楚起见的另一个示例:对于“数字”=“123452”和 b = 5(数字为 1、2、3、4、5)可能的序列是:

1.    "12345"
2.    "1234"
3.    "123"
4.    "12"
5.    "1"
6.    "2345"
7.    "234"
8.    "23"
9.    "2"
10.   "3452"
11.   "345"
12.   "34"
13.   "3"
14.   "452"
15.   "45"
16.   "4"
17.   "52"
18.   "5"
19.   "2"

结果将是“19”。

你对快速算法有什么想法吗?我想出的那个太慢了(比较每个数字)。

【问题讨论】:

  • 您想要子字符串的数量还是全部打印出来?该算法可接受的时间复杂度是多少?
  • 仔细阅读我写了子串的数量。我认为它可以在 O(n) 中完成,但我不确定。
  • 这是 O(n) 问题,如果您将使用 O(1) 时间集。看我的回答。

标签: c++ regex string algorithm substring


【解决方案1】:

将布尔表作为一个集合(第n个元素为true表示n在实际区间内)

现在很容易。您应该只遍历数组并扩大区间,当您找到重复的元素时,您只需移动区间的开头,直到达到唯一的序列。

为了更好的解释一些代码:

unsigned long long number_of_seq(string seq) {
  set<char> in_use; //Can be some O(1) set, pointless
  unsigned long long result = 0ULL;
  //p - begin of actual interval
  //q - end of this interval
  for(size_t p = 0, q = 0; q < seq.size();) {
       while(in_use.count(seq[q]) != 0) { //While: add seq[q] makes interval not unique
            in_use.erase(seq[p]);
            ++p; //move begin of interval
        }
       in_use.insert(seq[q]);
       ++q;
       result += q - p; //add size of interval
   }
  return result;
 }

您应该添加任何间隔的大小,因为您只是在末尾添加新元素,所有子字符串都是正确的(没有 2 个相同的字符),并且所有没有新字符的子字符串都会被考虑。是 seq[0:q] 和 seq[q] 中最大的唯一子串,所以是正确的。

【讨论】:

  • 我做了类似的事情(使用布尔表),但它的工作速度太慢了。
  • @MichałKryszak 如果您不想打印所有间隔,该解决方案是 O(n)。 O(n³) 如果你愿意,因为这里可以是 n² 正确的序列。我坚信这将很难克服。
  • 我猜它正在工作......虽然我不太了解所有代码......谢谢。
  • 我认为我需要大量改进我的数据结构才能在算法方面做得更好:P
  • 但是,此代码因更大的输入而失败,因此有点没用。
【解决方案2】:

查看Longest common subsequence problem,查看“读出所有 LCS”部分并巧妙地使用矩阵,您将获得所需的一切。

【讨论】:

  • OP 询问的是子字符串,而不是子序列。你确定这是相关的吗?
【解决方案3】:
int count(std::string seq, int len) {
   int sum = 0;
   bool elem[256] = {0};
   int i = 0, j = 0;
   while ( i < len ) {
      while ( !elem[seq[j]] && j < len) {
         elem[seq[j]] = true;
         j++;
      }
      sum += j - i;
      elem[seq[i]] = false;
      i++;
   }
   return sum;
}

我想不出比这更有效的解决方案了。祝你好运。

【讨论】:

  • 我不认为std::string[] 是你想要的。
  • 检测到碰撞后没有考虑到一些字符。这个解决方案是不正确的。以 OP 的帖子为例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多