用于部分文本搜索的快速算法

时间:2019-06-02 08:22:54

标签: c# regex algorithm

我有描述动作的单词列表,例如:

New
Open
Save
Save as
Copy
Paste
Cut
Select all

我希望用户仅通过连续输入几个字母就能找到命令。因此,如果用户输入例如“ ae”,则他应该收到:

sAvE
sAvE as
pAstE

通常,当用户输入“ abc”时,我想返回所有与正则表达式.*a.*b.*c.*匹配的字符串。由于验证字符串是否匹配此表达式是线性的,而bruteforce算法也是线性的,因此正则表达式对优化搜索没有多大帮助。

此列表的重要之处在于它在编译时是已知的,因此我可以设计一个数据结构,该数据结构将包含所有这些术语以加快搜索速度。

除了O(m * n)(其中m是项数,n是平均项长度)之外,是否有数据结构或算法可以加快找到特定用户输入的所有匹配词的时间?

3 个答案:

答案 0 :(得分:3)

这听起来像是我过早优化的情况。荒谬地过早。即使您有70个命令而不是七个,顺序搜索所有命令所花费的时间也非常短,以至于用户不会注意到它。而且这并不是您每秒要调用数百或数千次的函数。因此,花费数小时来执行一次精美的搜索以节省几毫秒的时间,而这只是浪费时间。用户可能会在程序的整个生命周期内节省的时间甚至与您花在设计,编写和调试优化的解决方案上的时间几乎不相干。

您有少量非常短的命令。电脑速度很快。这里没有问题要解决。花时间在实际上将使用户受益的功能上。

现在,如果要搜索的字符串数量非常多(成千上万),则可能会受益于某些优化。在这种情况下 。 。

您可以首先制作一个以字母为键的字典,其值是包含该字母的所有单词的列表。因此,您的示例将类似于:

$verbose == 6

然后,在字典中输入“字母跟随字母”。这将很快变得越来越大。例如,“粘贴”将具有以下条目:

pa   ps   pt   pe   如   在   e   圣   SE   te

您可以继续为更长的子字符串设置这些键。例如,您得到:

pas   拍   e   太平洋标准时间   se   pte

当字符串较短时,这可能非常有效。当字符串变长时,它的效率降低,因为包含特定字母组合的字符串的可能性随着字符串长度的增加而增加。

您可以通过创建trie来节省一些空间,但是该方法本质上是相同的。

也可能有用:suffix treegeneralized suffix tre e。

答案 1 :(得分:0)

正如我在评论中写道,也许您不必太担心性能...

但是,此数据结构应满足您的需求,我们称其为:Y树前的字母X。基本上是一棵树,如果该字母出现在目标单词中的父节点字母之后,则每个节点都有每个字母的子代 对于每个节点,您将存储所有匹配项的列表。

flags
in
line
lines
no

您可以用所有已知的名称预先填充它

public class Node
{
    public char Letter { get; set; }

    public Node[] Children {get;set;}

    public List<string> CommandNames {get;set;} 
}

匹配搜索词仅意味着遍历用户输入的每个字母的树,因此将其归结为O(n)

答案 2 :(得分:0)

我对其时间的复杂性了解不多,但是,如果我们只想搜索其中必须包含ae的单词,我们将以类似于接下来,我们将针对运行时进行优化:

(?=.*a)(?=.*e).*

测试

using System;
using System.Text.RegularExpressions;

public class Example
{
    public static void Main()
    {
        string pattern = @"(?=.*a)(?=.*e).*";
        string input = @"New
Open
Save
Save as
Copy
Paste
Cut
Select all";
        RegexOptions options = RegexOptions.Multiline;

        foreach (Match m in Regex.Matches(input, pattern, options))
        {
            Console.WriteLine("'{0}' found at index {1}.", m.Value, m.Index);
        }
    }
}

Demo

相关问题