标签:ar 代码 on c amp new 算法 r res
常见的字符串匹配时,模式串长度为n,源串长度为m,则从头匹配,两个指针i指向源串,j指向模式串,如遇到不同则回溯使j=0,这样就要重复匹配会使效率变低。
由于在现在i之前 的模式串与匹配串的匹配是相同的,即回溯时,不用将模式串与源串进行匹配,而只将模式串与自身匹配即可得到其是否需要回溯以及回溯到何处。则我们可以在进行模式匹配之前,想对模式串进行自我匹配,来计算出对于i在模式串的任意位置匹配失败后回溯的位置。
而对于自身匹配的算法还有一个优化的地方在于,模式串在b位置匹配到自身的a位置,然后判断一下这两个位置的字符是否相同,如果相同,则将a位置的回溯位置赋值给b,如果不同,则说明没有必要回溯到这个位置,因为回溯后不匹配,则直接将其置为0,表示从0开始重新匹配、
失败函数的返回值为-1是用来设置其结构,使其能够在自我匹配时简单实现其功能,标识匹配失败重新开始,但其在模式匹配中效果与0相同,都是i置为0,j++,然后继续匹配。
自我匹配放在一个失败函数中,对模式字符串进行操作,然后将结果放在一个数组中方便查询。
试着写出c++代码:
这里每次遍历时,是判断第i个字符串如果相同,那么第i加一个字符串不符就要返回的位置,每次都是对i+1进行操作,所以最后一次会对数组中下标为n的字符进行操作,会越界,则之前建fail数组时,要考虑一下。
void FailString(int f[],const char* str){ int length = strlen(str); int i =0, k = -1; f[0] = -1; while( i < length){ if(k == -1 || str[i] == str[k]){ i++;k++; if(str[i] == str[k]) f[i] = f[k]; else f[i] = k; }else k = f[k]; } } bool compareString(const char* charA,const char* charB){ if( charA == 0 || charB == 0) return false; int Alen = strlen(charA); int Blen = strlen(charB); if( ! Alen || ! Blen ) return false; if( Blen > Alen)return false; int* fail = new int[ Blen+1 ]; FailString(fail,charB); int i = 0 , j = 0; while(i < Alen && j < Blen){ if( charA[i] != charB[j] ){ if(fail[i] == -1 ) j = 0; else j = fail[i]; }else j ++; i++; } delete[] fail; fail =NULL ; return j==Blen; } void main(){ char* s1 = "abcabcaabcabbac"; char* s2 = "abcabcabbac"; if(compareString(s1,s2)) cout<<"s1==s2"<<endl; cin.get(); }
标签:ar 代码 on c amp new 算法 r res
原文地址:http://blog.csdn.net/luo_xianming/article/details/39372433