问题是我有一个大约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"
我试图查看列表并将字符串与子字符串匹配并删除子域。 这更清楚了吗?
答案 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
在所有计算中,平衡是效率/性能和内存。你会为了性能而牺牲内存,或者为了节省内存而牺牲性能,但是很难同时获得这两种内存。 :)