匹配次数最多的子序列?

时间:2011-08-25 16:46:32

标签: c# algorithm haskell

给定2d数据数组,我如何找到最匹配的最大组合?

示例:

Cust #  Prod #
C1      P1
C1      P2
C2      P1
C2      P3
C3      P1
C3      P3
C3      P4

(使用haskell - 无法弄清楚如何在C#中轻松实现这一点) 子序列是:


    > subsequenc­es ["P1"­,"P2","P3"­, "P4"]­
    => [[],["P1"],["P2"],["P1","P2"],["P3"],["P1","P3"],["P2","P3"],["P1","P2","P3"],["P4"],["P1","P4"],["P2","P4"],["P1","P2","P4"],["P3","P4"],["P1","P3","P4"],["P2","P3","P4"],["P1","P2","P3","P4"]]

我想找到X大小的子序列,其中包含多于Y个匹配...

因此,对于此示例,具有多个匹配的最大子序列为:[“P1”,“P3”] - 具有2个计数

因为个别客户序列是:


    C1 => ["P1, "P2"]
    C2 => ["P1", "P3"]
    C3 => ["P1", "P3", "P4"]

因此,这些集合中有两个[“P1”,“P3”]实例。

我最初的想法是生成子序列然后匹配,但我的数据集太大了。

注意:我的数据集有13000个独特的2D数据组合,因此子序列方法要么溢出要么根本不会完成,具体取决于语言。

编辑:我对最长的子集(未订购)感兴趣

编辑:@Jimmy:如果您将以下内容添加到列表中,我希望看到P1,P2,P4作为结果,因为它拥有最多的客户。遗憾的是,您的解决方案不起作用

    { "C4", new HashSet<string>(new[] { "P1", "P2","P4"})},
    { "C5", new HashSet<string>(new[] { "P1", "P2","P4"})},
    { "C6", new HashSet<string>(new[] { "P1", "P2","P4"})},

编辑:@Eric Lippert

我的理想输出是每个组合,每次都是一个子集。然后,我可以查询最大的篮子,并且该篮子中的商品数量最少。

编辑:从业务角度来看,我想找到许多客户购买的最常出现的商品。我意识到很多篮子的大小都很模糊 - 但这就是对结果进行分析的地方。

4 个答案:

答案 0 :(得分:3)

这个问题可以表述如下(如果我理解你的话):

给定n组:C1 ... CN, 每个由元素{P1 ... PN}

组成

找到这些子集的X与至少Y个元素的交集。

找到这些N个集合的最大子集交集的更复杂问题是NP-Hard (参见此proof)。

您的问题可能也是NP-Hard或NP-complete(因为它看起来像是找到最大交集的问题的决定版本)。您将无法找到解决问题的有效方法。

您应该查找最大子集交集问题的启发式方法,或者查找一些类似(但不同)和更受欢迎的问题(例如集合覆盖问题)的灵感。

答案 1 :(得分:0)

你所拥有的与此类似 1 a | 1 b | 1 c

2 a | 2 b

3 c | 3 d

相当于

abc | ab | cd

所以基本上你要解决的问题必须是  1.找到最大长度字符串  2.查找具有最大频率的字符串  3.其组合

将系列表示为矢量,为该矢量编写自定义比较函数,将它们添加到multiset,同时保持计数。并记住迄今为止最频繁序列遇到的最大计数,并记住插入的最长载体。

答案 2 :(得分:0)

只回答最长的子序列:

customer c = entryList[0].customer;
product p;
set s;
set largestSet = s;
for (every entry in entryList)
{
  if(c ! = entry.customer)
   {  
     c = entry.customer;
     if (s.size > largestSet.size)    largestSet = s;
     s.clear();
   }

   s.add(entry.customer)
}

答案 3 :(得分:0)

您似乎正在寻找最长的成对子集。

这是一种蛮力的方式:

从元组列表(c,p)开始,制作一个{c:set(p1,p2,p3)}字典。

var dict = new Dictionary<string, HashSet<string>> {
    { "C1", new HashSet<string>(new[] { "P1", "P2"})},
    { "C2", new HashSet<string>(new[] { "P1", "P3"})},
    { "C3", new HashSet<string>(new[] { "P1", "P3","P4"})},
};
var max = from pair1 in dict
          from pair2 in dict
          where pair2.Key != pair1.Key
          let s = pair1.Value.Intersect(pair2.Value).ToArray()
          orderby s.Length descending
          select s;

Console.WriteLine(string.Join(",", max.First()));

<小时/> 输出:

P1,P3

似乎是一个O(N ^ 3)算法。