【问题标题】:Count of subarray子数组的计数
【发布时间】:2018-02-20 01:35:57
【问题描述】:

问题是子数组计数的变体。给定一个数字数组,假设1,2,2,3,2,1,2,2,2,2 我查找子数组并计算每个子数组的频率。我从一些K 长度子数组开始(例如K = 3)。

子数组1,2,2 的计数是C1:2

子数组2,2,3 的计数是1

子数组2,3,2 的计数是1

等等。

现在,我寻找长度为 2 的子数组。 子数组1,2 的计数为C2: 2。但是 (1,2) 是子数组1,2,2 的子集。所以,我通过从C2 中减去C1 来计算它的计数,这使得1,2 的计数为0。同样,2,2 的计数为1。 我的问题是处理存在多个父子集的情况。我不考虑结果集中频率为 1 的子数组。示例: 1,2,3,1,2,3,1,2,2,3

这里,1,2,3 的计数是 2

2,3,1 的计数是 2

现在,当我查找 2,3 的计数时,它应该是 1,因为所有更长的父母都已经涵盖了这些事件。我该如何处理这些情况?

我认为的方法是标记父级的所有模式出现。在上述情况下,标记所有出现的1,2,32,3,1。数组如下所示:

1,2,3,1,2,3,1,2,2,3

X,X,X,X,X,X,X,2,2,3

其中 X 表示标记位置。现在,根据未标记的位置,我们看到的2,3 的频率为 1。所以,基本上,我标记了我在当前步骤中找到的所有模式出现。下一步,我开始从未标记的位置寻找模式,只是为了得到正确的计数。

我正在处理大量数据,这似乎不太好做。另外,我不确定它是否正确。任何其他方法或想法可以有很大帮助吗?

【问题讨论】:

  • 不清楚你到底在计算什么——你为什么要从 C2 中减去 C1?为什么在第二个示例中 2,3 的计数应该是 1?
  • 如果您看到,在第二个示例中,2,3 的计数为 3。但是在长度为 3"1,2,3" 的子数组中已经出现了 2 次。 (1,2,3),(1,2,3),1,2,2,2,3。因此,最后的 2,3 只在计数中。
  • 但是 2,3 也是 2,3,1 和 2,2,3 的子数组。为什么你只对 1,2,3 感兴趣?
  • @algrid 已编辑。 (2,3) 的计数应该是 1,因为所有更大的长度父母,(1,2,3) 和 (2,3,1) 已经涵盖了这些事件。我不考虑计数为 1 的子数组。

标签: arrays algorithm count subset sub-array


【解决方案1】:

为给定数组构建suffix array

计算所有给定长度的重复子数组h - 遍历这个后缀数组,按所需前缀长度比较相邻后缀。
对于你的第一个例子

source array 
1,2,2,3,2,1,2,2,2,2
suffix array is 
5,0,9,4,8,7,6,1,2,3:

1,2,2,2,2              (5)
1,2,2,3,2,1,2,2,2,2    (0)
2                      (9)
2,1,2,2,2,2            (4) 
2,2                    (8)
2,2,2                  (7)
2,2,2,2                (6)
2,2,3,2,1,2,2,2,2      (1)
2,3,2,1,2,2,2,2        (2)
3,2,1,2,2,2,2          (3)

长度为 2 我们可以计算两个子数组1,2 和四个子数组2,2

如果你想计算任何给定的子数组 - 例如,所有以(1,2) 开头的后缀,只需使用二分搜索来获取第一个和最后一个索引(如std:upperbound 和@987654327 C++ STL 中的 @ 操作)。
对于相同的示例,(1,2)在后缀数组中的第一次和最后一次出现的索引是 0 和 1,因此计数是 last-first+1=2

【讨论】:

  • 如果我尝试为第一个示例构建后缀数组,其中数组为 1,2,2,3,2,1,2,2,2,2,则后缀数组将为 5,0 ,9,8,7,6,4,2,1,3。您现在如何计算任何子数组的出现次数?例如,如果我想数 1,2。您要查找所有以 (1,2) 开头的后缀吗?举个例子真的很有帮助。
  • 我已经添加了更多解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-20
  • 1970-01-01
相关资源
最近更新 更多