我有一个字节数组(可以变得非常大,超过3200万字节),我需要用相同长度的其他子数组替换一些子数组。
我当前的方法是在字节数组中搜索我需要替换的所有子数组,每次我找到一个将子数组的索引添加到列表中,然后继续。
我的代码如下。我有一种唠叨的感觉,这不能有效,因为3200万字节需要超过10秒才能完成搜索和替换。我传递8个字符串来替换,所以它基本上最终搜索16个子数组。
任何人都会看到我的算法存在任何缺陷或更有效的缺陷吗?
附:我实际上并没有在这段代码中替换它们,只是找到索引。我的代码应该非常有效。
public class Search
{
public List<int> positions;
public List<int> lengths;
private List<byte[]> stringsToSearchFor;
public Search(List<string> strings){
stringsToSearchFor = new List<byte[]>();
positions = new List<int>();
lengths = new List<int>();
foreach (string tempString in strings){
stringsToSearchFor.Add(Encoding.ASCII.GetBytes(tempString));
stringsToSearchFor.Add(Encoding.Unicode.GetBytes(tempString));
}
}
public void SearchBytes(byte[] haystack){
int[] arrayOfInt = new int[stringsToSearchFor.Count];
bool[] arrayOfBoolean = new bool[stringsToSearchFor.Count];
for (var i = 0; i < haystack.Length; i++){
byte currentByte = haystack[i];
for (int stringCounter = 0; stringCounter < arrayOfBoolean.Length; stringCounter++)
{
byte[] stringLookFor = stringsToSearchFor.ElementAt(stringCounter);
byte currentStringByte = stringLookFor[arrayOfInt[stringCounter]];
//Saying the current byte is the desired one
if (currentStringByte == currentByte)
{
if (arrayOfInt[stringCounter] + 1 == stringLookFor.Length){
positions.Add(i - stringLookFor.Length + 1);
lengths.Add(stringLookFor.Length);
arrayOfInt[stringCounter] = 0;
}
else
{
arrayOfInt[stringCounter]++;
}
}
else
{
arrayOfInt[stringCounter] = 0;
}
}
}
return;
}
}
答案 0 :(得分:3)
我可以看出SearchBytes()
只有2个嵌套for
循环,这个暴力搜索算法有一个bug。这种蛮力搜索需要3个嵌套循环:对于每个针脚中的每个起始位置,对于每个针线,您需要一个循环来检查整个针是否出现在大海捞针中的那个位置。 (如果发现字符不匹配,这个最里面的循环可能会提前中止。)
这是一个具体的例子:如果干草堆是ABCABCABD
并且你的一根针串是ABCABD
,那么这个字符串将无法找到,尽管它确实发生了。那是因为一旦你的算法看到大海捞针中的第二个C
,它就会得出结论,它必须从大海捞针中的当前位置开始寻找针头,而实际上它需要从较早的位置开始寻找。
无论如何,用于在长度为n的草堆中搜索单个长度为m的针串的蛮力的时间复杂度为O(nm),如果两者都是中等长度则非常可怕。 John Kurlak suggested Knuth-Morris-Pratt or Rabin-Karp,如果你正在寻找一些大的字符串,那么运行其中任何一个肯定会加快速度(以及正确 :-P),但是有效地专门针对的算法在字符串中查找多个字符串称为Aho-Corasick algorithm。需要时间O(n + s + k),其中n是干草堆大小,s是要搜索的针串大小的总和,k是任何针串的出现次数 - 这是很漂亮的很难被击败。
答案 1 :(得分:2)
你基本上是在进行暴力搜索。你可以做更类似于Knuth-Morris-Pratt或Rabin-Karp字符串搜索算法的事情(而不是在字符串中搜索字符序列,而是在数组中搜索字节序列),而不是做蛮力。