你能用字符串比较在字符串列表上运行二进制搜索吗?

时间:2014-03-11 14:02:59

标签: c#

问题是我有一个大约800,000个字符串元素的列表,并尝试匹配字符串的子字符串。是的,现在我通过详尽的搜索(蛮力)来做到这一点,但那需要几个小时。我希望有一种更快更优雅的方法

namespace Sorting_Program_Ver1_1
{
class Program
{
    static void Main(string[] args)
    {
        string[] tempStringArray; string[] dataStringArray; string[] dotdotStringArray;
        List<string> myList = new List<string>();
        List<string> twoDots = new List<string>();
        Console.WriteLine("Starting program - initialising variables");

        tempStringArray = File.ReadAllLines("C:\\datadomains");
        int count = 0;

        for (int a = 0; a < tempStringArray.Length - 1; a++)
        {
            if (tempStringArray[a].Length > 0)
            {
                myList.Add(tempStringArray[a]);
            }
        }
        Console.WriteLine("Adding items to string list");

        for (int b = 0; b < myList.Count; b++)
        {
            for (int c = 0; c < myList[b].Length; c++)
            {
                if (myList[b][c] == '.')
                {
                    count++;
                }
            }
            if (count == 2)
            {
                twoDots.Add(myList[b]);
            }
            count = 0;
        }
        Console.WriteLine("Sorting the list into 2");

        dotdotStringArray = twoDots.ToArray();
        System.IO.File.WriteAllLines("C:\\twoDots.txt", dotdotStringArray);

        Console.WriteLine("Starting the search...");
        for (int d = 0; d < twoDots.Count; d++)
        {
            for (int e = myList.Count - 1; e > 0; e--)
            {
                if (myList[e] == "")
                {
                    Console.WriteLine("Removing empty space...");
                    myList.RemoveAt(e);              
                }

                int start = myList[e].Length - twoDots[d].Length;
                if (start >= 0)
                {
                    if (twoDots[d] == myList[e].Substring(start, twoDots[d].Length))
                    {
                        if (twoDots[d] != twoDots[d])
                        {
                            Console.WriteLine("Removing...", myList[e]);
                            myList.RemoveAt(e);
                        }
                    }                       
                }
            }
        }

        Console.WriteLine("Saving to file ...");
        dataStringArray = myList.ToArray();
        System.IO.File.WriteAllLines("C:\\myList.txt", dataStringArray);
        Console.WriteLine("Saved to file");
        Console.WriteLine("Exit program");
    }
}

}

示例:

mylist[0]= ".bob.com"
mylist[1]= ".steve.bob.com"
mylist[2]= ".steve.job.bob.com"
...
mylist[800000]= ".coffee.com"

substring=".bob.com"

我试图查看列表并将字符串与子字符串匹配并删除子域。 这更清楚了吗?

3 个答案:

答案 0 :(得分:2)

二进制搜索在这里不是一个选项,因为这意味着整个树本身处于某种顺序(并且理想地平衡)。由于您想要进行部分比较,因此顺序并不重要,因此二元搜索无济于事。

您可能需要查看Boyer-Moore字符串搜索算法,该算法非常有效,特别是对于长字符串。

http://www.akira.ruc.dk/~keld/teaching/algoritmedesign_f05/Artikler/09/Boyer77.pdf查看。如果你只是谷歌为#Bo; Boyer-Moore&#34;你还应该能够找到一些有趣的链接,例如关于算法的书中的这一章:http://orion.lcg.ufrj.br/Dr.Dobbs/books/book5/chap10.htm

还有一种名为Breslauer-Grossi-Mignosi的更新算法(您可以在http://www.stupros.com/site/postconcept/Breslauer-Grossi-Mignosi.pdf找到)。我还没有研究过那个,所以我不能评论它。

答案 1 :(得分:0)

如果您对字符串的完全相等感兴趣,或者您正在查找从您正在搜索的字符串的开头开始的子字符串,则只能执行二进制搜索。不是,所以不,你不能使用二进制搜索。

答案 2 :(得分:0)

如果您正在寻找字符串的任何部分作为子集,那么您希望构建的是后缀Trie。实际上没有有效负载,但是您可以构建整个文本的所有已知后缀的Trie,这可以在文本的单个O(n)遍历中完成。这比内存中只有一个大字符串占用了更多的内存,但它是一种非常有效的方式来存储与字符串相关的数据。搜索子字符串然后是针对trie的O(m)操作(其中m是您正在搜索的子字符串的长度),这将是非常快速的。

如果你只想匹配整个单词,你也可以将所有单词放入HashSet<string>,也许使用构造函数重载来忽略大小写,然后对给定的单词进行O(1)检查。< / p>

后缀树(Trie变体没有出现有效负载):http://en.wikipedia.org/wiki/Suffix_tree

在所有计算中,平衡是效率/性能和内存。你会为了性能而牺牲内存,或者为了节省内存而牺牲性能,但是很难同时获得这两种内存。 :)