我建议使用字典。使用字符串作为键,使用字符串列表作为值。标记将要搜索的字符串,并为每个标记将整个字符串添加到字典中一次。 (您可以使用 split 方法对字符串进行标记。使用空格作为分隔符。)此后,每当您需要进行查找时,您可以对搜索字符串进行标记,并对字典中的每个标记执行查找。
因此,如果您添加了以下字符串:foo、baz、bar、blah、foo bar、foo baz
您的字典有条目:
foo: foo, foo bar, foo baz
巴兹:巴兹,富巴兹
酒吧:酒吧,富酒吧
废话:废话
然后你应该搜索“foo bar”,
您的输出是存储在 foo 和 bar 下的条目的并集,如下所示:
"foo bar":= foo, bar
foo: foo, foo bar, foo baz
联盟
酒吧:酒吧,富酒吧
给予:foo, foo bar, foo baz, bar
编辑:我刚刚注意到您只想要完整或部分匹配,即 foo baz 是不可接受的。简单的解决方案是对结果进行后期处理——将搜索字符串和目标字符串中较长的字符串限制为较短字符串的长度,然后将截断的字符串与未修改的字符串进行比较。只接受那些等效的。
编辑:所以事实证明 foo baz 确实是匹配的。忽略上面的段落(第一次编辑)。
见(C#)代码如下:
class DictionarySearch
{
private Dictionary<string, List<string>> dict;
public DictionarySearch()
{
dict = new Dictionary<string, List<string>>();
}
/// <summary>
/// Add a string e.g. foo bar to the dictionary
/// </summary>
/// <param name="s">string to be added</param>
public void addString(string s)
{
//tokenize string
string[] words = s.Split(new char[] { ' ' });
//add each token to the dictionary as a key with the matching value being s
foreach (string w in words)
{
if (dict.ContainsKey(w))
{
dict[w].Add(s);
}
else
{
dict.Add(w, new List<string>());
dict[w].Add(s);
}
}
}
/// <summary>
/// Find all strings which match at least one token
/// </summary>
/// <param name="s">string of tokens (words) to be matched</param>
/// <returns>List of strings matching at least one word</returns>
public IList<string> getMatches(string s)
{
//split search string into words
string[] words = s.Split(new char[] { ' ' });
List<string> output = new List<string>();
//retrieve from dictionary list of strings matching each word.
foreach (string w in words)
{
if (dict.ContainsKey(w))
{
output.AddRange(dict[w]);
}
else
{
continue;
}
}
return output;
}
}
给定一个包含 m 个字符串的字典,每个字符串有 q 个单词和 n 个唯一单词,以及一个包含 l 个单词的搜索字符串,时间复杂度如下:
填充数据结构:O(qmT[dictionary-insert])。需要对每个单词进行一次插入
查找字符串:O(l*T[dictionary-find])。搜索字符串中每个单词的字典查找。
实际成本取决于您的字典实施。基于哈希表的字典会产生插入和查找的 O(1) 成本。基于二叉树的字典在插入和查找时都会产生 O(lg n) 成本。