技术至上    发表日志    管理页面    退出登陆

 



«December 2025»
123456
78910111213
14151617181920
21222324252627
28293031


 公告
 
在此正式宣布,这个Blog下的地盘,都是偶的啦  这个版面专用于技术...别的就先不贴了!

专题分类

日志更新

最新评论

留言板

链接


信息
blog名称:技术至上
日志总数:4
评论数量:1
留言数量:0
访问次数:73483
建立时间:2004年12月11日





[Algorithms]KMP、Monte Carlo、Las Vegas 匹配算法 (用C++ & STL实现)
原创空间,  软件技术

Stanley 发表于 2004/12/11 19:59:02

// StrMatcher.cpp : 定义控制台应用程序的入口点。 #include "stdafx.h"#include "basicmatcher.h" #include <stdlib.h>#include <stdio.h>#include <time.h> #define STRING_NUM 10000 //素数(Prime Number)产生器,这里利用讲义中提供的7素数分类,而非自行产生//PNM is short for "Prime Number Matrix"namespace PNM{ //不同范围内的素数矩阵 int pnm[6][7]={  {211,223,227,229,233,239,241},  {461,463,467,479,487,491,499},  {953,967,971,977,983,991,997},  {4957,4967,4969,4973,4987,4993,4999},  {9923,9929,9931,9941,9949,9967,9973},  {100003,100019,100043,100049,100057,100069,100103} };  //根据m、n的大小确定M,并随机抽取一个适当的素数 //注意在全局调用前应使用srand((unsigned)time(NULL)); int Generate(const CmpStrPair& csp){  int m=csp.second.second,n=csp.first.second;  int M=2*m*n*n;  //M=2*m*n*n  int N=rand()%7;  //N为随机数(0<=N<=6)  if(M>0 && M<=250) return pnm[0][N];  else if(M>250 && M<=500) return pnm[1][N];  else if(M>500 && M<=1000) return pnm[2][N];  else if(M>1000 && M<=5000) return pnm[3][N];  else if(M>5000 && M<=10000) return pnm[4][N];  else return pnm[5][N]; }}; //计时器变量clock_t start,step;//计时结果double total_time,run_time; int _tmain(int argc, _TCHAR* argv[]){ //产生大于5000组的随机串 CmpStrVector csv; Romdomizer rmd; for(int i=0;i<STRING_NUM;i++){  rmd.Romdomize(csv); }  //就上述产生的随机串进行各类匹配操作  //KMP KMP kmp(csv[0]); start=clock(); for(int i=0;i<STRING_NUM;i++){  kmp.ReSet(csv[i]);  kmp.FastFind(); } step=clock(); total_time=double(step-start)/CLOCKS_PER_SEC; run_time=total_time/STRING_NUM; cout<<"KMP Approach :"<<endl; cout<<"Total Time : "<<total_time<<endl  <<"Run Time : "<<run_time<<endl<<endl  <<"--------------------------------"<<endl<<endl;  //Monte Carlo MonteCarlo mc(csv[0]); start=clock(); for(int i=0;i<STRING_NUM;i++){  mc.ReSet(csv[i]);  mc.Compare(PNM::Generate(csv[i])); } step=clock(); total_time=double(step-start)/CLOCKS_PER_SEC; run_time=total_time/STRING_NUM; cout<<"Monte Carlo Approach :"<<endl; cout<<"Total Time : "<<total_time<<endl  <<"Run Time : "<<run_time<<endl<<endl  <<"--------------------------------"<<endl<<endl;  //Las Vegas LasVegas lv(csv[0]); start=clock(); for(int i=0;i<STRING_NUM;i++){  lv.ReSet(csv[i]);  lv.Compare(PNM::Generate(csv[i])); } step=clock(); total_time=double(step-start)/CLOCKS_PER_SEC; run_time=total_time/STRING_NUM; cout<<"Las Vegas Approach :"<<endl; cout<<"Total Time : "<<total_time<<endl  <<"Run Time : "<<run_time<<endl<<endl  <<"--------------------------------"<<endl<<endl;  cout<<"Monte Carlo Approach's Mistake-Rate Is :"  <<1-float(lv.match_num)/float(mc.match_num)<<endl;  return 0;} //Utility.h : 辅助工具的定义 #include<iostream>#include<string>#include<bitset>#include<limits>#include<vector>#include<utility> using namespace std; //程序中用到的一些预定义和函数namespace def{ //比特流原型,包含了比特流的数值信息 typedef bitset<numeric_limits<unsigned long>::digits> Bits; //比特流模拟串:后项为串实际长度(前截断) typedef pair<Bits,unsigned int> BitString; //比较串对:前项为源串,后项为目标串 typedef pair<BitString,BitString> CmpStrPair; //比较串对向量:用来存储已经生成的比较串对序列 typedef vector<CmpStrPair> CmpStrVector; //打印比特串BitString ostream& operator << (ostream& os,BitString& b_str);}; using namespace def; //随机数列产生器类class Romdomizer{public: Romdomizer(); //将生成的比较串对送到待处理序列中 void Print(ostream& os=cout){  os<<"Source : "<<source<<endl    <<"Target : "<<target<<endl; } bool Romdomize(CmpStrVector&); void Romdomize();  //随机生成新比较串对private: void Create(long& v,unsigned int& s,bool isSource); //随机产生比特串的必要构成:v,比特串值、s:比特串长  BitString source;  //比较源串X:x1,...,xn BitString target;  //比较目标串Y:y1,...,ym}; //Utility.cpp : 辅助工具的实现 #include "stdafx.h"#include "Utility.h" #include <stdlib.h>#include <stdio.h>#include <time.h> //--------------------------------------------------------------------------------------------- namespace def{ ostream& operator << (ostream& os,BitString& b_str){  for(int i=b_str.second-1;i>=0;i--)   os<<b_str.first[i];  return os; }}; //--------------------------------------------------------------------------------------------- Romdomizer::Romdomizer(){ //根据时间设置随机 srand((unsigned)time(NULL));} void Romdomizer::Create(long& v,unsigned int& s,bool isSource){ //串长度的最大值(目标串的最大长度应为源串的长度,根据isSource是否成真确定是否为源串) size_t size_max; long value_max=1;  //根据随即产生的串长度决定串值可能取的最大值  //计算串长度的最大值 if(isSource){  size_max=numeric_limits<unsigned long>::digits; } else  size_max=static_cast<size_t>(3*s/4+1);//为了增加成功率,假设目标串较短,长度不到源串3/4 //产生随机串长度 s=rand()%size_max+1; //根据串长计算串值的最大值 for(int i=static_cast<int>(s);i>0;i--)  value_max*=2; value_max--; //产生随机串值 v=value_max*(float(rand())/float(RAND_MAX));} void Romdomizer::Romdomize(){ long t_value=0;   //临时串值 unsigned int t_size=0; //临时串长度 //随机生成源串 Create(t_value,t_size,true); source=make_pair(Bits(t_value),t_size); //随机生成目标串 Create(t_value,t_size,false); target=make_pair(Bits(t_value),t_size);} bool Romdomizer::Romdomize(CmpStrVector& v){ if(v.size()<v.max_size()){  Romdomize();  CmpStrPair t_p(source,target);  v.push_back(t_p);  return true; } return false;} // BasicMatcher.h : 基本匹配函数的定义 #include "Utility.h" //说明:这里使用BitString特殊表现形式,以下方法采用反向匹配机制//即ym,...,y1与xn,...,x1匹配,如果成功,则原先的正向串也必然匹配//反之,则原先的正向串必然不匹配 class KMP{public: KMP(CmpStrPair& csp):p_source(&csp.first),p_target(&csp.second){  for(int i=0;i<numeric_limits<unsigned long>::digits;i++)   fail[i]=-2;  Fail(); } inline void ReSet(CmpStrPair& csp){  p_source=&csp.first;  p_target=&csp.second;  for(int i=0;i<numeric_limits<unsigned long>::digits;i++)   fail[i]=-2;  Fail(); } int FastFind();     //KMP的主匹配函数private: void Fail();     //失效函数 BitString* p_source;   //源串的引用 BitString* p_target;   //目标串的引用 int fail[numeric_limits<unsigned long>::digits];}; class MonteCarlo{public: MonteCarlo(CmpStrPair& csp):p_source(&csp.first),p_target(&csp.second),match_num(0){;} inline void ReSet(CmpStrPair& csp){  p_source=&csp.first;  p_target=&csp.second; }  //Monte Carlo的匹配主函数 //p:随机产生的素数 int Compare(int p); int match_num;private: BitString* p_source;   //源串的引用 BitString* p_target;   //目标串的引用}; class LasVegas{public: LasVegas(CmpStrPair& csp):p_source(&csp.first),p_target(&csp.second),match_num(0){;} inline void ReSet(CmpStrPair& csp){  p_source=&csp.first;  p_target=&csp.second; }  //Last Vegas的匹配主函数 //p:随机产生的素数 bool Verify(int pos); int Compare(int p); int match_num;private: BitString* p_source;   //源串的引用 BitString* p_target;   //目标串的引用}; //BasicMatcher.cpp : 基本匹配函数的实现 #include "stdafx.h"#include "BasicMatcher.h" void KMP::Fail(){ int length=p_target->second; fail[0]=-1; for(int j=1;j<length;j++){  int i=fail[j-1];  while(p_target->first[j]!=p_target->first[i+1] && i>=0) i=fail[i];  if(p_target->first[j]==p_target->first[i+1]) fail[j]=i+1;  else fail[j]=-1; }} int KMP::FastFind(){ int posS=0,posT=0; int lenS=p_source->second,lenT=p_target->second; while(posT<lenT && posS<lenS)  if(p_target->first[posT]==p_source->first[posS]){   posT++;   posS++;  }  else if(posT==0) posS++;  else posT=fail[posT-1]+1; if(posT<lenT)  return 0; else return posS-lenT+1;//方向匹配结果} int MonteCarlo::Compare(int p){ int n=p_source->second,m=p_target->second; int j=0; int temp=1;  //用以求得2的m次方 for(int i=0;i<m;i++)  temp*=2; int Wp=temp % p; //求源串指纹 //先求以X0开头m位的数值value作为递推的起点; long value=0; for(int i=0;i<m;i++){  value*=2;  int bit=p_source->first[i]?1:0;  value+=bit; } int Ipx=value % p; int Ipy=p_target->first.to_ulong() % p; //求目标串指纹 while(j<n-m){  if(Ipx==Ipy){   match_num++;   return j+1;  }  //根据公式计算Ipx  int t1=p_source->first[j]?1:0;  int t2=p_source->first[j+m]?1:0;  Ipx=(2*Ipx+t1*Wp+t2) % p;  j++; } return 0;} bool LasVegas::Verify(int pos){ for(int i=0;i<p_target->second;i++){  if(p_target->first[i]!=p_source->first[pos+i])   return false; } return true;} int LasVegas::Compare(int p){ int n=p_source->second,m=p_target->second; int j=0; int temp=1;  //用以求得2的m次方 for(int i=0;i<m;i++)  temp*=2; int Wp=temp % p; long value=0; for(int i=0;i<m;i++){  value*=2;  int bit=p_source->first[i]?1:0;  value+=bit; } int Ipx=value % p; int Ipy=p_target->first.to_ulong() % p; //求目标串指纹 while(j<n-m){  //加入了验证环节  if(Ipx==Ipy && Verify(j)) {   match_num++;   return j+1;  }  //根据公式计算Ipx  int t1=p_source->first[j]?1:0;  int t2=p_source->first[j+m]?1:0;  Ipx=(2*Ipx+t1*Wp+t2) % p;  j++; } return 0;}


阅读全文(5479) | 回复(1) | 编辑 | 精华
 



发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)

站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.023 second(s), page refreshed 144818642 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号