簡體   English   中英

哪種數據結構和算法適合於此?

[英]Which data structure and algorithm is appropriate for this?

我有一千串。 給定一個需要在所有字符串中搜索的模式,然后返回包含該模式的所有字符串。

目前,我正在使用vector來存儲原始字符串。 搜索模式,如果匹配,則將其添加到新向量中,最后返回向量。

int main() {
    vector <string> v;
    v.push_back ("maggi");
    v.push_back ("Active Baby Pants Large 9-14 Kg ");
    v.push_back ("Premium Kachi Ghani Pure Mustard Oil ");
    v.push_back ("maggi soup");
    v.push_back ("maggi sauce");
    v.push_back ("Superlite Advanced Jar");
    v.push_back ("Superlite Advanced");
    v.push_back ("Goldlite Advanced"); 
    v.push_back ("Active Losorb Oil Jar"); 

    vector <string> result;

    string str = "Advanced";

    for (unsigned i=0; i<v.size(); ++i)
    {
        size_t found = v[i].find(str);
        if (found!=string::npos)
            result.push_back(v[i]);
    }

    for (unsigned j=0; j<result.size(); ++j)
    {
        cout << result[j] << endl;
    }
    // your code goes here
    return 0;

}

是否有任何最佳方法可以以更低的復雜度和更高的性能實現相同目標?

我認為適合您的應用程序的容器。

但是,如果您實現自己的KMP algorithm ,則可以代替std::string::find ,而是可以保證時間復雜度在字符串+搜索字符串的長度方面是線性的。
http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm

因此, std::string::find的復雜性是不確定的。
http://www.cplusplus.com/reference/string/string/find/

編輯:如此鏈接所指出,如果您的字符串的長度不大(大於1000),則可能使用std::string::find就足夠了,因為這里不需要制表等。
C ++ string ::發現復雜性

如果結果與輸入字符串向量在同一代碼塊中使用(在您的示例中就是這樣),或者即使您保證每個人都僅在輸入存在時才使用結果,則實際上不需要復制字符串。 這可能是一個昂貴的操作,從而大大降低了整個算法的速度。

相反,您可以將指針向量作為結果:

vector <string*> result;

如果字符串列表在許多搜索中都是“固定的”,那么您可以使用倒排索引進行一些簡單的預處理,從而大大加快處理速度。

構建字符串中存在的所有字符的映射,換句話說,為每個可能的字符存儲一個包含該字符的所有字符串的列表:

std::map< char, std::vector<int> > index;
std::vector<std::string> strings;

void add_string(const std::string& s) {
    int new_pos = strings.size();
    strings.push_back(s);
    for (int i=0,n=s.size(); i<n; i++) {
        index[s[i]].push_back(new_pos);
    }
}

然后,當被要求搜索子字符串時,您首先要檢查反向索引中的所有字符,然后僅在條目數最少的索引的列表上進行迭代:

std::vector<std::string *> matching(const std::string& text) {
    std::vector<int> *best_ix = NULL;
    for (int i=0,n=text.size(); i<n; i++) {
        std::vector<int> *ix = &index[text[i]];
        if (best_ix == NULL || best_ix->size() > ix->size()) {
            best_ix = ix;
        }
    }

    std::vector<std::string *> result;
    if (best_ix) {
        for (int i=0,n=best_ix->size(); i<n; i++) {
            std::string& cand = strings[(*best_ix)[i]];
            if (cand.find(text) != std::string::npos) {
                result.push_back(&cand);
            }
        }
    } else {
        // Empty text as input, just return the whole list
        for (int i=0,n=strings.size(); i<n; i++) {
            result.push_back(&strings[i]);
        }
    }
    return result;
}

可能有許多改進:

  • 使用更大的索引(例如使用成對的連續字符)
  • 避免考慮非常常見的字符(停止列表)
  • 使用從三元組或更長序列計算出的哈希
  • 搜索相交而不是搜索較短的列表。 給定元素的添加順序,無論如何矢量都已經排序,甚至可以使用矢量有效地計算交集(請參閱std::set_intersection )。

根據問題的參數(搜索多少個字符串,搜索多長時間,搜索多長時間……),它們是否都有意義。

如果源文本很大且是靜態的(例如,已爬網的網頁),則可以通過預先構建后綴樹trie數據結構來節省搜索時間。 然后,搜索模式可以遍歷樹以找到匹配項。

如果源文本很小並且經常更改,那么您的原始方法是合適的。 STL函數通常經過很好的優化,並經受了時間的考驗。

暫無
暫無

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

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