如何(快速)找到c# /. net中最长的匹配字符串?
本文关键字:字符串 net 快速 找到 如何 | 更新日期: 2023-09-27 18:16:07
我需要对一组项做一些查找操作。
首先我需要看看是否有直接匹配。这很简单,因为我有一个Dictionary<String,MyObjectType>
的条目,所以我可以直接写dictionary["valuetofind"]
。
然而,如果没有直接匹配,那么我需要做一个开始匹配,但它必须是返回的最长匹配:
记录的例子:
String Record
0 A
01 B
012 D
02 B
03 C
查询例子:
Query Result
0 A - Because 0 is the longest match
01 B - Because 01 is the longest match
023456 B - Because 02 is the longest match
012 D - Because 012 is the longest match
0123456 D - Because 012 is the longest match
03456 C - Because 03 is the longest match
04 A - Because 0 is the longest match
0456 A - Because 0 is the longest match
1 Null - No Match
是否有类在框架中有哈希或树结构的后台实现做这样的事情,或者我需要自己写一些东西?
编辑到目前为止,我所拥有的是按模式字符串长度排序的列表,然后我一个接一个地查看条目,以查看查询是否从记录开始。这在大多数情况下都可以工作,因为我们还没有大的列表,但是在没有匹配的情况下,成本很高。
我没有足够的词汇量让谷歌给我一些与哈希集、列表和字典无关的页面。我发现所有的研究都指向基于树的结构,但没有一个指出是否已经在。net框架中实现了。
Leppie and Spender是正确的;如果数据集变得很大,你想要实现的有效解决这个问题的数据结构是一个"trie",或者,如果你真的很熟练,一个DAWG——一个有向无循环词图。如果字符串有许多常见后缀,则DAWG具有更好的内存性能,但它们更昂贵且难以构建和更新,因此从trie开始。
您的简单案例将生成如下所示的树:
ROOT
|
0|
|
A
/ | '
/ | '
1/ 2| 3'
/ | '
/ | '
B B C
|
2|
|
D
所以要查找023456,你从根开始,沿着标记为0的分支找到A,然后沿着分支2找到B,那里没有分支3,所以你完成了。
顺便说一下,这也是你在给定字典和一组字母的情况下查找最长的Scrabble单词时使用的数据结构;这其实是同一个问题。
. net框架中没有内置的trie数据结构,但它不是一个很难构建的数据结构。我这里有一个不可变的trie,我一直想在博客上写一下;如果我有机会的话,我会在这里发布一个链接。
一个相当简单的方法是brute force
他们。我假设您有一个Dictionary<string, string> _lookupTable
来保存查找
string Find(string query)
{
var retval = null;
while(!string.IsNullOrEmpty(query) && retval == null)
{
if(!_lookupTable.TryGetValue(query, out retval))
query = query.Substring(0, query.Length-1);
}
return retval;
}
你可以扫描整个字典寻找最长的匹配
string sQuery = "01234";
int iMaxLength = 0;
foreach (KeyValuePair<String, String> kVP in mD)
{
if (sQuery.Contains(kVP.Value) && (kVP.Value.Length > iMaxLength))
{
iMaxLength = kVP.Value.Length
result = (whatever...)
}
}
看起来,您应该使用简单地按长度排序的二叉树,然后查找第一个匹配。我不认为像二叉树这样的东西已经在c#中实现了,但是快速搜索一下就会发现很多网站已经这样做了。