假设我们有以下列表:
List<int> Journey1 = new List<int>() { 1, 2, 3, 4, 5 };
List<int> Journey2 = new List<int>() { 2, 3, 4, 6, 7, 3, 4 };
List<int> Journey3 = new List<int>() { 6, 7, 1 };
List<int> Journey4 = new List<int>() { 3, 1, 4 };
模式是:
2, 3, 4 -> Journey1, Journey2;
6, 7 -> Journey2, Journey3;
1 -> Journey2, Journey3, Journey4;
5 -> Journey1;
3, 4 -> Journey2;
3 -> Journey4;
4 -> Journey4;
我们有5000个列表,每个列表大约有200个项目,因此模式可以有1-200个项目,可以在1-5000个列表中看到。
因此我需要非常快速的模式匹配方式。
答案 0 :(得分:2)
没有预先计算和天真的即时搜索:
var matchedJourneys = journeys.Where(x => ContainsPattern(x, mypattern));
bool ContainsPattern(List<int> list, List<int> pattern)
{
for(int i = 0; i < list.Count - (pattern.Count - 1); i++)
{
var match = true;
for(int j = 0; j < pattern.Count; j++)
if(list[i + j] != pattern[j])
{
match = false;
break;
}
if(match) return true;
}
return false;
}
这将执行最多2亿等于检查您的'数字'。但是,由于预计不会对整个模式执行检查,如果检查所有列表,那可能是(仅仅是一个猜测)〜500万等于操作。那是几百毫秒。
这一切都取决于对你来说“非常快”。如果这太慢了,你需要一个更复杂的方法......
答案 1 :(得分:1)
我不确定你想要什么作为输出。我刚试了一次。
我建议您列出一个列表,而不是声明单个列表变量。
List<List<int>> journeys = new List<List<int>>();
journeys.Add(new List<int>() { 1, 2, 3, 4, 5 });
journeys.Add(new List<int>() { 2, 3, 4, 6, 7, 3, 4 });
journeys.Add(new List<int>() { 6, 7, 1 });
journeys.Add(new List<int>() { 3, 1, 4 });
我假设数字范围从0到255.使用此查询
var result = Enumerable.Range(0, 256)
.Select(number => new
{
number,
listIndexes = journeys
.Select((list, index) => new { index, list })
.Where(a => a.list.Contains(number))
.Select(a => a.index)
.ToList()
})
.Where(b => b.listIndexes.Count > 0)
.ToList();
和这个测试循环
foreach (var item in result) {
Console.Write("Number {0} occurs in list # ", item.number);
foreach (var index in item.listIndexes) {
Console.Write("{0} ", index);
}
Console.WriteLine();
}
你会得到这个结果
Number 1 occurs in list # 0 2 3 Number 2 occurs in list # 0 1 Number 3 occurs in list # 0 1 3 Number 4 occurs in list # 0 1 3 Number 5 occurs in list # 0 Number 6 occurs in list # 1 2 Number 7 occurs in list # 1 2
列表从零开始编号。
答案 2 :(得分:0)
对于暴力攻击方法,您可以尝试使用polynomial hash-functions加速子节匹配。仍然需要进行疯狂的比较,但至少匹配可能几乎不变,无论子序列长度如何。
答案 3 :(得分:0)
在您的情况下,有机会受益于模式预处理以及文本预处理(http://en.wikipedia.org/wiki/String_searching_algorithm)。
例如,为列表中的所有子序列构造trie将允许在时间上与模式长度成比例地查询给定模式的列表。