是否有任何算法可以在某些模式中对数组进行分类?

时间:2012-12-15 18:14:56

标签: c# algorithm search pattern-matching decision-tree

对于一个简单的数组长度为5的问题(实际上数组长度可能是20 ..)

我有一个预定义的模式集,例如 AAAAB,AAABA,BAABC,BCAAA,...... 每个模式与输入数组的长度相同。我需要一个函数,它将任何整数数组作为输入,并返回所有它匹配的模式。 (数组可能会匹配一些模式)尽快。

A ”表示在模式中,A位置的所有数字都相等。例如。 AAAAA 仅表示所有数字相等, {1,1,1,1,1} 匹配 AAAAA

B ”表示位置B处的数字不等于A位置处的数字。(即不是A的数字的通配符)数字表示的数字B不必相等。例如。 ABBAA 表示第1,第4,第5个数字等于,例如x,第2个,第3个不等于x。 {2,3,4,2,2} 匹配 ABBAA

C ”表示此位置可以是任意数字(即数字的通配符)。 {1,2,3,5,1} 匹配 ACBBA {1,1,3,5,1} 也匹配 ACBBA

我正在寻找一种有效的(在比较数字方面)算法。它不一定是最优的,但不应该是最佳的。我觉得它有点像决策树......

一种非常直接但效率低下的方式如下:

  • 尝试根据输入匹配每个模式。对 {a> b,c,d,e} AABCA 。它会检查(a=b=e && a!=c)

  • 如果模式数量 n ,模式/数组的长度 m ,则复杂度约为 O(n *米)

更新

请随意为问题提出更好的措辞,因为我不知道如何在不混淆的情况下简单理解问题。

理想的算法需要某种准备,比如将模式集转换为决策树。因此,对于某些特殊模式集,可以实现 预处理之后的复杂性,例如O(log n * log m)。(只是猜测)

一些可能有帮助的数字:预定义的模式集大小大小为30.要匹配的输入数组的数量大约为1000万。

说,如果 AAAAA AAAAC 都在预先定义的模式集中。然后,如果 AAAAA 匹配, AAAAC 也会匹配。我正在寻找一种可以识别的算法。

更新2

@Gareth Rees的回答给出了一个O(n)解决方案,但假设没有多少“ C ”。 (否则存储空间巨大且需要进行许多不必要的比较)

我也欢迎有关如何处理有很多“ C ”的情况的任何想法,例如,对于长度为20的输入数组,至少有10“ C “对于每个预定义模式。”

2 个答案:

答案 0 :(得分:6)

这是一个为O​​( n ) - ish运行时交换O(2 n )准备和存储的想法。如果您的阵列不超过机器的字大小(暗示20是典型大小),或者模式中出现的 C 太多,这个想法可能适合您。 (如果这些条件都不满足,请避免!)

  1. (准备步骤,完成一次。)创建字典 d 将数字映射到模式集。对于该模式中出现 C 的每个模式 p 和每个子集 S ,让 n 为具有与模式中的每个 A 对应的设置位的数字,以及 S 中每次出现 C 的数字。将 p 添加到模式集 d [ n ]。

  2. (每次需要将新数组与模式匹配时,都会执行剩余步骤。)创建字典 e 将数字映射到数字。

  3. j 遍历数组的索引,并为每个 j

    1. i 成为数组中的 j -th整数。

    2. 如果 i 不在词典 e 中,请设置 e [ i ] = 0

    3. 设置 e [ i ] = e [ i ] + 2 ℓ - j - 1 其中ℓ是数组的长度。

  4. 现在 e 的键是数组中的不同数字 i ,值 e [ i ]具有与阵列中每次出现 i 相对应的设置位。对于在词典 d 中找到的每个值 e [ i ],集合 d 中的所有模式[ e [ i ]]匹配数组。

  5. (注意:实际上你会反过来构建位集,并在步骤3.3使用2 j 而不是2 ℓ - j - 1 ,但为了清晰起见,我用这种方式描述了算法。)

    这是一个例子。假设我们的模式是 AABBA ACBBA 。在预处理步骤中, AABBA 变为数字25(二进制为11001), ACBBA 变为数字25(二进制为11001)和17(二进制为10001),对于模式中出现 C 的两个可能子集。所以字典 d 看起来像这样:

    • 17→{ ACBBA }
    • 25→{ AABBA ACBBA }

    在处理数组{1,2,3,5,1}之后,我们有 e = {1→17,2→8,3→4,5→2}。 e [1] = 17的值可在 d 中找到,因此此输入与 ACBBA 模式匹配。

    在处理数组{1,1,2,3,1}后,我们 e = {1→25,2→4,3→2}。 e [1] = 25的值可在 d 中找到,因此此输入符合 AABBA ACBBA 模式。

答案 1 :(得分:0)

获取模式中第一个A的索引,获取该位置的值,然后遍历这些位置。

要检查数组array是否与字符串pattern中的模式匹配,结果是布尔值match

int index = pattern.IndexOf('A');
int value = array[index];
bool match = true;
for (int i = 0; i < array.Length; i++) {
  if (pattern[i] != 'C' && i != index) {
    if ((pattern[i] == 'A') != (array[i] == value)) {
      match = false;
      break;
    }
  }
}