KMP演算法與string::find以及strstr的比較

來源:互聯網
上載者:User

首先,簡單描述一下KMP演算法,要理解好KMP演算法,最好參考演算法導論[1],尤其是先理解好自動機匹配的方法,再看KMP就很容易理解了。它利用的是一個關鍵的回退原理,也就是如果匹配失敗時,那麼我知道只要從模式的某個位置繼續匹配就可以了,這個回退的位置事先通過模式計算出來,也就是說如果某個位置匹配不成功,就回退到事先算好的位置,繼續匹配。這個事先算好的位置就是從0到該位置應該是匹配不成功處的一個尾碼。這個過程可以通過已經算好的回退位置來遞推出來。

從演算法的描述看,回退的數組的構建與匹配的過程是非常相似的。

這裡比較了KMP和string::find以及strstr的效能,代碼如下:

#include <vector>#include <string>#include <stdio.h>#include <stdlib.h>#include <sys/time.h>#include <string.h>void ComputePrefixFun(const std::string& patten, std::vector<int>* back) {  int k = -1;  (*back).push_back(-1);  for (int i = 1; i < patten.size(); ++i) {    while (k > -1 && patten[k + 1] != patten[i]) {      k = (*back)[k];    }    if (patten[k + 1] == patten[i]) {      k++;    }    (*back).push_back(k);  }}void Match(const std::string& src, const std::string& patten, const std::vector<int>& back, std::vector<size_t>* offset) {  int k = -1;  size_t src_length = src.size();  size_t patten_length = patten.size();  for (int i = 0; i < src_length; ++i) {    while (k > -1 && patten[k + 1] != src[i]) {      k = back[k];    }    if (patten[k + 1] == src[i]) {      k++;    }    if (k == patten_length - 1) {      (*offset).push_back(i - patten_length + 1);      k = back[k];    }  }}std::string IntToString(int value) {  std::string res = "";  do {    res.insert(0,std::string(1, value % 10 + '0'));  } while ((value /= 10) >0);  return res;}int GetTime() {  timeval tv;  gettimeofday(&tv, NULL);  return tv.tv_sec * 1000000 + tv.tv_usec;}int main(int argc, char** argv) {  std::string patten = "1212123";  std::vector<int> back;  std::string src = "";  for (int i = 0; i < 1000000; ++i) {    src += IntToString(rand());  }  ComputePrefixFun(patten, &back);  std::vector<size_t> offset;  int start = GetTime();  Match(src, patten, back, &offset);  printf("time:%d %zd\n", GetTime() - start,  offset.size());  start = GetTime();  int index = -1;  int count = 0;  while ((index = src.find(patten, index + 1)) != std::string::npos)  {    count++;  }  printf("time:%d count = %d\n", GetTime() - start, count);  const char* pos = src.c_str();  start = GetTime();  count = 0;  while (true) {    pos = strstr(pos, patten.c_str());    if (pos == NULL) break;    pos++;    count++;  }  printf("time:%d find:%d \n", GetTime() - start, count);  std::string matched = "";  for (int i = 0; i < offset.size(); ++i) {    matched = src.substr(offset[i], patten.size());    //    printf("%zd %s ", offset[i], matched.c_str());  }  printf("\n");}

開始編譯時間沒有使用最佳化選項,結果KMP的效能總是不理想,使用-O3編譯後,效能明顯改善了。

參考文獻

演算法導論 第32章 P586

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.