首先推荐这篇KMP思想的介绍:字符串匹配的KMP算法
KMP代码的关键是:
1、得到搜索串每个字符的匹配值
2、当字符匹配失败时的转移
(搜索串指搜索目标串。)
1:
第一个循环:遍历每个字符,表示搜索的是 该字符及之前所有字符组成的串。
第二个循环:遍历所有长度的子串。
第三个循环:比较子串是否相同。
搜索的目标是:所有相同的子串中最长字串的长度。所以维护一个maxl变量。
(在此“子串”指前缀和后缀。)
(代码中未清零model数组。)
2:
匹配失败时的转移就很简单了。
若当前字符匹配失败,前一字符的model值就是前面已匹配串的前缀与后缀相同的个数,直接令搜索串的偏移等于该数值就行。(代码不同由于数组脚标可能会有+-1差别。)
void inis(string t, int* model){ //初始化得到搜索串的模式 //第一个循环 i为字符串尾 for(int i=1; i<=t.size(); i++){ //第二个循环 k为字串长度 for(int k=1; k<i; k++){ //cout<<"k:"<<k<<endl; int maxl = 0;//最长匹配子串的长 bool ok = true; //第三个循环 h为子串比较的位 for(int h=0; h<k; h++){ //cout<<"h:"<<h<<"--"<<t[h]<<" "<<t[i-k+h]<<endl; if(t[h] == t[i-k+h]){ maxl++; }else{ ok = false; break; } // cout<<h<<"-"<<len-k+h<<endl; } if(ok && maxl>model[i-1]){ model[i-1] = maxl; } } } } int sf(string s, string t, int* model, int off){ //从偏移off处开始搜索 返回目标串首字符从0开始的索引 int slen = s.size(); int tlen = t.size(); int i=off, k=0; for( ; i<slen; i++){ //cout<<"i:"<<i<<endl; //cout<<s[i]<<" "<<t[k]<<endl; if(s[i] == t[k]){ //cout<<"k++ "<<k<<endl; k++; }else{ //状态转移 if(k != 0){ k = model[k-1]; i--; } } if(k == tlen){ return i - k + 1;//首 //return i;//尾字母 } } return -1; }
原文地址:http://blog.csdn.net/windroid/article/details/45013851