在给定条件下长度N的数量内的所有可能序列

时间:2014-10-29 20:49:29

标签: c++ regex string algorithm substring

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

对于我们的例子" 12211"我们可以说有7个序列:

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

结果将是" 7"。

另一个清晰的例子:" Number" =" 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"。

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

3 个答案:

答案 0 :(得分: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],所以它是正确的。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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;
}

我无法想到比这更有效的解决方案。祝你好运。