Horspool 演算法C++11實現(支援中英文混合搜尋)

來源:互聯網
上載者:User

標籤:c++11   horspool   algorithm   

摘要:

本文給出一個horspool演算法的實現,展示一個使用樣本,並向介紹一個非常好用的UTF8字元轉碼項目,給出一個簡單的測試報告等。

演算法實現:

#include <iostream>#include <unordered_map>//#include <codecvt>#include <fstream>#include <iterator>#include <sstream>#include <bitset>#include "utf8.h"using namespace std;template <typename Key,typename Value>class ShiftTable{  public:        ShiftTable(const std::u32string& pattern){            index_=pattern.size();            auto end=pattern.rbegin();            auto head=pattern.rend();            auto cur=end+1;            while(cur!=head){              shiftTable_.emplace(make_pair(*cur,cur-end));              ++cur;            }        }        Value operator [](const Key& key){            auto cur=shiftTable_.find(key);            if(cur!=shiftTable_.end())              return cur->second;             else              return index_;        }    private:        unordered_map<Key,Value> shiftTable_;        size_t index_;};int HorspoolMatching(const std::u32string & pattern,const std::u32string & text){    if(pattern.empty()||text.empty())return -1;    ShiftTable<char32_t,size_t> table(pattern);    auto m=pattern.size();    auto n=text.size();    auto i=m-1;    while(i<=n-1){        int k=0;        while(k<=m-1&&pattern[m-1-k]==text[i-k]) k++;        if(k==m)            return i-m+1;        else            i+=table[text[i]];    }    return -1;}


在這裡不對horspool 演算法進行闡述,僅分享一個實現而已。

實現中使用std::u32string, 並且我們要求字元採用unicode32,以支援任意國建字元竄的搜尋。

在這裡我強烈推薦大家關注一個輕量開源的utf8轉碼實現,這個是項目首頁utf8

一個使用例子,尋找並替換:

int main(){    //一種比較高效,純C++方式把檔案讀入字串    ifstream filestream("/home/ron/input.in");//該檔案需要以utf8格式儲存(作業系統無要求)    stringstream ss;    ss<<filestream.rdbuf();        string text(ss.str());    string pattern="你是";//此處"你是"是utf8儲存的,因為源碼在ubuntu下以utf8儲存    std::u32string  text32;    std::u32string  pattern32;    utf8::utf8to32(text.begin(), text.end() , back_inserter(text32));    utf8::utf8to32(pattern.begin(), pattern.end() , back_inserter(pattern32));        string repWord="我";//此處"我"是utf8儲存的,因為源碼在ubuntu下以utf8儲存    std::u32string repWord32;    utf8::utf8to32(repWord.begin(), repWord.end() , back_inserter(repWord32));    //尋找檔案中的"你是"    auto index=HorspoolMatching(pattern32,text32);    if( index!=-1 )    {        cout<<"found it,at index "<<index<<endl;        text32.replace(index,1,repWord32);         //替換檔案中,第一"你是"為"我是"        ofstream ofilestream("/home/ron/input.in");        ostream_iterator<char> out(ofilestream);        utf8::utf32to8(text32.begin(),text32.end(),out);    }    else    {        cout<<"not found"<<endl;    }    return 0;}

上述代碼,是一個使用樣本,它可以跨平台(作業系統支不支援utf8無所謂,我們程式支援utf8/16/32 任意轉碼),所以只要求輸入檔案和模式字串是採用utf8編碼即可。我們知道utf8是網路傳輸採用的標準,並且大多數系統均支援utf8。

我們可以做支援任何編碼的尋找,那樣問題就複雜化了,誰願意無窮盡的陷入到字元編碼中,相信只有這個領域的專家吧。

codecvt:

#include <codecvt>

這個標頭檔是啥?C++11引入的關於字元竄轉碼的實現,可惜gcc到現在還沒有實現,哎,怎麼會?。vc2010以後的版本應該是支援的。有興趣的同學可以自行瞭解。因為我編譯環境是ubuntu gcc所以無法使用codecvt,還有其他的一些字元編碼庫可以用,類似ICU等等,但他們太大了,用起來也麻煩。終於找到utf8輕量級項目,copy源碼即用,它在ubuntu下表現非常好。當然在window下也一樣。缺點無非就是僅支援utf而已。

測試:

我使用一些文本對這個實現和標準庫實現進行對比,時間效能效率相差無幾(標準庫略好一點點)。有一個gcc issue,希望採用Boyer-Moore演算法實現find。所以我猜測gcc對find實現很可能採用的就是horspool演算法,又快又簡單,只是最壞複雜度無法保證。

KMP:

怎麼不見KMP,KMP太複雜了。除非你對演算法有所癖愛,否則沒有任何一個程式員會選擇效率相同,但實現更複雜的演算法。但KMP演算法的思想確實對後續其他演算法產生了影響。


限於本人水平,歡迎大家批評指正。轉載請表明出處,謝謝。

Horspool 演算法C++11實現(支援中英文混合搜尋)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.