第32章:字符串匹配问题: 朴素算法,Rabin-Karp算法
来源:互联网 发布:圣思园java视频百度云 编辑:程序博客网 时间:2024/05/18 03:14
在文本编辑中,经常要找出某一个模式在一段文本中全部出现的位置。这可以用字符串匹配问题来求解,不过这一章节仅考虑长度有限的字符串。如果一个模式P(长度为m)是从文本T(长度为n)中第(s+1)个字符开始出现,我们则说模式p在文本T中出现并且位移为s(0<=s<=n-m)。
本章节给出了求解字符串匹配问题的四种算法,分别是朴素算法,Rabin-Karp算法,有限自动机算法,Knuth-Morris-Praat算法。除了朴素算法外,另外三个算法都对模式P进行了一些预处理,然后找寻所有位移,我们称第二步为匹配。在这篇文章中,先介绍朴素算法和Rabin-Karp算法。
朴素算法:
朴素算法应该属于暴力搜索法,用一个循环找出所有有效位移s(0<=s<=n-m),该循环对n-m+1个可能的每一个s值检查模式P是否与文本中从第s+1个字符开始匹配。代码如下:
//判断模式字符串P是否与从文本中位置pos开始的字符串匹配(文本从位置0开始);template<class C>bool is_equal(const C& P,const C& T,size_t pos){ for(size_t i=0;i!=P.size();++i) if(P[i]!=T[pos+i]) return false; return true;}void naive_string_matcher(const string& T,const string& P){ size_t n=T.size(); size_t m=P.size(); if(n<m){ cout<<"the length of patter is greater than the length of text!!"<<endl; return; } for(int s=0;s<=n-m;++s) if(is_equal(P,T,s)) cout<<"pattern starts to occur from the "<<s+1<<"th character of Text"<<endl;}
这个算法由于没有对模式P进行预处理,因此预处理时间为0,匹配时间为O((n-m+1)*m),因为对s的for循环有(n-m+1)步,is_equal函数所花费的时间为O(m)。
Rabin-Karp算法:
假设文本T和模式P的元素都是来自一个有限子母集C的字符,我们可以把C中的字符等价地转化为数字,C={0,1,2,…,d-1}(d为字母集C中元素的个数,也称做基数),依据C中字符转化数字的关系,我们相应地也把文本T和模式P中的字符也转换成了数字。
假设给定了一个素数q。给定一个由数字组成的模式P[0…(m-1)],令p表示相应的d进制值对q的模
p=[P[m-1]+d(P[m-2]+10(P[m-3]+…+10(P[1]+10P[0])…))]%q.
类似地,给定一个由数字组成的文本T[0…(n-1)],假设
我们可以用求p相同的方法来求
有一个细节需要主要的是,我们应该要确保
Rabin-Karp算法代码如下:
//to calculate a^b%c;unsigned long mod(unsigned long a, unsigned long b, unsigned long c){ unsigned long ret=1; unsigned long tmp=a%c; while(b!=0){ if(b%2!=0) ret=(ret*tmp)%c; b/=2; tmp=(tmp*tmp)%c; } return ret;}void Rabbin_Karp_matcher(const vector<unsigned long>& T,const vector<unsigned long>& P,unsigned long d,unsigned long q){ size_t n=T.size(); size_t m=P.size(); // to calculate d^(m-1)%q; unsigned long h=mod(d,m-1,q); //to calculate T[0...(m-1)]%q,P[0...(m-1)]%q; unsigned long p=0; unsigned long t=0; for(size_t i=0;i!=m;++i) { p=(d*p+P[i])%q; t=(d*t+T[i])%q; } // to find the match of P in T; for(size_t s=0;s<=n-m;++s) { if(p==t) if(is_equal(P,T,s)) cout<<"pattern starts to occur from the "<<s+1<<"th character of Text"<<endl; if(s<n-m){ long tmp=d*(t-T[s]*h)+T[s+m]; //if tmp<0, the result of tmp%q is machine independent.The case should be avoided. if(tmp<0){ tmp=-tmp; int k=0; while(++k){ if(tmp<k*q){ tmp=k*q-tmp; break; } } } t=tmp%q; } }}
Rabin-Karp算法计算p和
- 第32章:字符串匹配问题: 朴素算法,Rabin-Karp算法
- Rabin-Karp字符串匹配算法
- 字符串匹配--Karp-Rabin算法
- Rabin-Karp字符串匹配算法
- Rabin-Karp 字符串匹配算法
- 算法导论-第32章-字符串匹配:Rabin-Karp算法C++实现
- 字符串匹配算法 朴素算法 Rabin—Karp算法,KMP算法
- 字符串匹配算法之Rabin-Karp算法
- 字符串匹配算法 -- Rabin-Karp 算法
- 算法-字符串匹配(String Matching)-(1)-朴素匹配和Rabin-Karp算法
- Rabin-Karp字符串匹配算法c源代码
- 字符串匹配之Rabin-Karp算法
- 字符串匹配之Rabin-Karp 算法
- 字符串匹配(一)——朴素算法,Rabin-Karp算法
- 字符串算法-Rabin-Karp
- 面试算法之字符串匹配算法,Rabin-Karp算法详解
- 朴素字符串匹配与Karbin-Karp算法
- 白话分析字符串匹配算法——Rabin-Karp算法
- JS学习17(JSON)
- Swift基础(二):运算符、字符串和字符、数组、集合、字典
- C/S和B/S的异同点
- 安装MySQL样本数据库Sakila
- Reacting to rumors
- 第32章:字符串匹配问题: 朴素算法,Rabin-Karp算法
- unity资源包的依赖关系(2)
- Runtime之概念,功能和怎么使用
- hdu 2923 Einbahnstrasse【floyd】
- Redis在Centos7上的安装部署
- byte数组转float 以及byte转其他类型时为什么要&0xff
- Genymotion无法启动虚拟机的问题解决办法(续)
- 排序算法的 时间复杂度 和 空间复杂度
- 如何编写一个分布式数据库