簡體   English   中英

加快字符串搜索算法

[英]Speed up string search algorithm

我正在使用這種簡單的算法來搜索文檔中的一些文本並標記我在哪一頁上找到的文本

for (int i = 1; i <= a.PageCount; i++)
{
    Buf.Append(a.Pages[i].Text);
    String contain = Buf.ToString();
    if (contain != "")
    {
        // Inside is dictionary of keys and value contain page where I found it
        foreach (KeyValuePair<string, List<string>> pair in inside)
        {
              if (contain.Contains(pair.Key))
                  inside[pair.Key].Add((i).ToString());
        }
    }

    Buf.Clear();
 }

我沒有問題,但是當我在700頁的文檔中搜索並且正在尋找500多個鍵時,它非常慢,大約需要1-2分鍾才能通過,請問有什么方法可以加快它的速度嗎? 我正在使用C#

謝謝!

幾點:

  • 擺脫Buf ; 只是分配a.Pages[i].Text直接contain
  • inside[pair.Key]浪費時間查找與該鍵關聯的值; 因為浪費了對pair.Value對該對象的引用,所以浪費了時間。
  • 如果您有一個整數值列表,為什么要將它們存儲為字符串?

樣例代碼:

for (int i = 1; i <= a.PageCount; i++)
{
    String contain = a.Pages[i].Text
    if (contain != "")
    {
        // Inside is dictionary of keys and value contain page where I found it
        foreach (KeyValuePair<string, List<int>> pair in inside)
        {
            if (contain.Contains(pair.Key))
                pair.Value.Add(i);
        }
    }
}

最后,確保Pages實際上確實使用基於一個的索引。 集合通常是零索引的。

因為編輯 Pages是一個字典:

foreach (KeyValuePair<int, Page> kvp in a.Pages)
{
    string contain = kvp.Value.Text;
    if (contain == "")
        continue;
    foreach (KeyValuePair<string, List<int>> pair in inside)
        if (contain.Contains(pair.Key))
            pair.Value.Add(kvp.Key);
}

您對第一個代碼示例進行了多少次? 時間取決於許多外部因素。 一種方法的一次運行比另一種方法的運行更快或更慢的事實並不能真正告訴您很多,特別是因為我提出的建議可能無法解決大部分問題。

正如其他人指出的那樣,主要問題是您要調用contain.Contains(pair.Key) 350,000次; 那可能是您的瓶頸。 您可以分析該方法以找出是否正確。 如果真的,那么像Miserable Variable建議的Rabin Karp算法之類的東西可能是您最好的選擇。

[[

編輯:以下內容無關緊要,因為您要在循環結束時清除Buf(盡管請注意,您實際上並不需要buf, string pageText = a.Pages[i].Text是您所需要的)

什么是Buf 你有

Buf.Append(a.Pages[i].Text);

這樣是否不迫使Contains通過越來越大的字符串查看? 我很驚訝您沒有用完700頁的內存。

]]

有更有效的方法來查看any of a set of strings中的any of a set of strings是否出現在另一個string 例如,您可以准備鍵的樹結構,因此不必多次比較。

請參閱Rabin-Karp算法

考慮現有的第三方庫,必須有一些。

我沒有700頁要測試,但是您可以嘗試使用正則表達式:

var s = Stopwatch.StartNew();
var r = new Regex(string.Join("|", from x in inside select Regex.Escape(x.Key)));

for (int i = 1; i <= a.PageCount; i++)
{
    foreach (Match match in r.Matches(a.Pages[i].Text))
    {
        inside[match.Value].Add(i.ToString());
    }
}

Console.WriteLine(s.Elapsed);

標准性能/調試過程-注釋掉部分代碼和度量。 一次又添加一次,直到變得“糟糕”為止。 那可能是您的問題所在。

例如,您可能首先注釋掉整個foreach。

似乎正在使用一些可能很復雜/昂貴的對象-內部,Buf等。注釋掉這些對象的用法,然后一次將它們放回去。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM