0.KMP
本节图文参考:http://blog.csdn.net/v_july_v/article/details/7041827
失配后,j = next[ j ]
寻找模式串中,各个子串的 { 所有前缀 } & { 所有后缀 } 的最大公共元素长度(前缀和后缀一样,那么失败后就可以直接从后缀开始了)
最大长度值,整体右移一位就成了next数组
next[ j ]=k 的意思是除当前字符 p[ j ]以外的最长前缀后缀(即:失败之后可以从模式串的哪儿开始)
#include
#include #include using namespace std; void getNext(string &sstr,vector &next) { next[0]=-1;//赋值-1,而不是0时,next[0]可以作为哨兵 int sl=sstr.size()-1; int j=0; int k=-1; while(j &next) { int ml=mstr.size(); int sl=sstr.size(); int i=0; int j=0; while(i next; for(int i=0;i 关于KMP:http://blog.csdn.net/v_july_v/article/details/7041827真的写得很好
KMP中next数组优化主要思想是:当sstr[ j ] ! = mstr[ i ]时,如果下个比较值sstr[ next [ j ] ]等于sstr[ j ]的话就不用再和s[ i ]比较了,必然会失配
1.RabinKarp#include
#include #include using namespace std; void getNextval(string &sstr,vector &next) { next[0]=-1;//赋值-1,而不是0时,next[0]可以作为哨兵 int sl=sstr.size()-1; int j=0; int k=-1; while(j &next) { int ml=mstr.size(); int sl=sstr.size(); int i=0; int j=0; while(i next; for(int i=0;i
主要思想是把大的字符串或者字母字符串等映射成小的、数字字符串,(模式串的话,直接映射成一个数字,这样比对的时候就可以x=y一次比对了,而不用像暴力法一样模式串一位一位的比对)这样就可以相较于暴力法快了。
如果模式串转换后的数字太大,可以先mod一个较大的质数。mod所带来的问题是,有些是伪正确(7%10=7,17%10=7),面对这个问题,只要将正确和伪正确(待选目标)用暴力法验证一下就行了(这时候的暴力法是有目标的,而不是盲目的,所以开销不会像纯粹暴力法那样夸张)。
#include
#include #include #include using namespace std; //为方便理解其核心思想,这里假设文本串T和模式串P都是由0~9的数构成。 //而且保证P转成数字之后,不会超出INT_MAX的范围,故也不再取模运算了 bool RabinKarp(string &T,string &P,const int &d) { int n=T.size(); int m=P.size(); int h=pow(d+0.0,m-1);//d^(m-1),类似于存储过程中2^0,2^1,2^2,2^3,2^4一样 int p=0;//转后不变的模式串 int t=0;//转后会变的m长度大小的文本串子串 for(int i=0;i