字符串匹配
来源:互联网 发布:数据库导论第五版答案 编辑:程序博客网 时间:2024/06/08 13:16
字符串匹配
问题描述
输入两个字符串A和B;
输出字符串B在字符串A中的位置。
示例
输入字符串“ABDABACDBD”和字符串“BACD”;
输出偏移量5,或输出在第一个字符串中“BACD”处的指针。
方法
常用方法有好多:朴素算法,Rabin-Karp算法,有限自动机算法,KMP算法。
复杂度对比:复杂度为预处理时间和匹配时间的和。
算法预处理时间匹配时间朴素算法0Ο((n-m+1)*m)Rabin-Karp算法Θ(m)Ο((n-m+1)*m)有限自动机算法Ο(m*字符集个数)Θ(m)Knuth-Morris-Prattu算法Θ(m)Θ(m)Boyer–Moore算法待搜索待搜索
朴素算法
通过循环找到所有有效偏移;
函数NaiveStringMatcher(char *A,char *T)实现在字符串A中匹配字符串T;
辅助函数CharacterMatcher(char *A,char *B,char *T)判断指针A和B之间字符串是不是和字符串T匹配。
bool CharacterMatcher(char *A,char *B,char *T){char *cc = A;int i = 0;while(cc != B){if(*cc != *(T+i))return false;cc++;i++;}return true;}void NaiveStringMatcher(char *A,char *T){int iLengthofA = strlen(A);int iLengthofT = strlen(T);for(int i = 0;i <= iLengthofA-iLengthofT ;i++){if(CharacterMatcher(A+i,A+i+iLengthofT,T))cout<<"Pattern occurs with shift"<< i+1 << endl;}}
Rabin-Karp算法1
将字符串做一种数的运算得到一个值,然后进行值的比较;
这个数值要求可以表示出字符的前后顺序,而且可以随时去掉某个字符的值,可以随时添加一个新字符的值。
例如A="12345",B="34",对于B采用运算(3*10+4)得到34作为B的值;采用相同运算方式对A进行运算,然后做比较。
如果相乘过大时,可以对一个较大的素数求模,然后比较。
double Encryption(char *A, int m,int q){int i =0;double sum = 0.0;while(i < m){sum = sum * q + ((int)*(A + i++)) ;}return sum;}int ChangeEncryption(char *A,int ll,int sum,int q){double mm = pow((double)q,(double)ll - 1);return ((sum - (int)mm * (*A)) * q + *(A + ll));}char * Rabin_Karp_Algo(char *A,char *B){int ll = strlen(B);double m = Encryption(B ,ll, 128);double n = Encryption(A ,ll, 128);char *cc = A;for(;*(cc+ll) != '\0';cc++){if(n == m){return cc;}n = ChangeEncryption(cc,ll,n,128);}return NULL;}
有限自动机算法2
在字符串A中搜索模式T,对于模式T中出现的所有可能情况看作不同状态。
如模式T为“ababaca”
建立状态0~7,分别对应{初始状态}、{a}、{ab}、{aba}、{abab}、{ababa}、{ababac}、{ababaca}。
计算对应状态转移表(计算方法后面讲到)。
static int delta[8][4]={ //转移函数 检测ababaca//a,b,c,*.{1,0,0,0}, //状态0 {初始状态}{1,2,0,0}, //状态1 {a,}{3,0,0,0}, //状态2 {ab,}{1,4,0,0}, //状态3 {aba,}{5,0,0,0}, //状态4 {abab,}{1,4,6,0}, //状态5 {ababa,}{7,0,0,0}, //状态6 {ababc,}{1,2,0,0} //状态7 {ababca,}};int State = 0; //初试状态
函数AutomationMatch(char *A)为匹配函数,返回位置指针。
char *AutomationMatch(char *A){int Length = strlen(A);char *cc = A;while(*cc != '\0'){int n = *cc++ - 'a';if(n != 0 && n != 1 && n != 2)n = 3;State = delta[State][n];if(State == 7)return cc-7;}return NULL;}
状态转移表计算
根据给定模式T[1..m]来计算。
伪代码为
COMPUTE-TRANSITION-FUNCTION(T,E)1 m=P.length2 for q = 0 to m3 for each charater a∈E4 k = MIN(m+1,q+1)5 repeat6 k = k - 17 until T[1..k] is tail of T[1..q]&a8 δ(q,a) = k9 return δ
c++代码
bool TT(char *T,int k,int q,char a){if(*(T + k-- - 1) != a)return false;while(k > 0 && q > 0){if(*(T + k - 1) != *(T + q - 1))return false;k--;q--;}return true;}int *TransitionFunction(char *T,char *E) //T为搜索模式,E为T的字符集{const int m = strlen(T);const int n = strlen(E);int *Ans[8][3];int q = 0,p = 0;int k = 0;for(;q <= m;q++){for(p = 0;p < n;p++){k = MIN(m+1,q+1);while(!TT(T,k,q,*(E+p)) && k>0){k = k-1;}*((int*)Ans + n * q + p) = k;}}return (int*)Ans;}
KMP算法3
详细解释看参考
代码
int *ComputePrefixFunction(char *P){int i = 1;int j = 0;int m = strlen(P);int *s = new int[m];memset(s,0,m * 8);while(i < m){while(P[i] == P[j] && i < m ){s[i] = s[i-1] + 1;j++;i++;}j = 0;i++;}return s;}void KMPMatcher(char *T,char *P){int n = strlen(T);int m = strlen(P);int q = 0;int *Map = ComputePrefixFunction(P);int i;for(i = 0 ; i < n ; i++){while(q > 0 && P[q] != T[i])q = Map[q-1];if(P[q] == T[i])q++;if(q == m){int gg = i -m +1 ;cout << "zhongduan:" << ends;printf("%d",gg);q = Map[q - 1];}}}
by:狼儿乖乖
time:2015/1/19 20:51:43
http://www.cnblogs.com/golove/p/3234673.html ↩
http://www.cnblogs.com/skyivben/archive/2009/05/21/1474398.html ↩
http://www.ruanyifeng.com/blog/2013/05/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm.html ↩
- 字符串匹配
- 字符串匹配
- 字符串匹配
- 字符串匹配
- 字符串匹配
- 字符串匹配
- 字符串匹配...
- 字符串匹配
- 字符串匹配
- 字符串匹配
- 字符串匹配
- 字符串匹配
- 字符串匹配
- 字符串匹配
- 字符串匹配
- 字符串匹配
- 字符串匹配
- 字符串匹配
- 【c++程序】用递增法在数组中查找数据
- Visual Studio 设置多处理器并行编译
- STL与泛型编程入门
- [python]split 和 join
- openGL es2.0 render坐标(三维) 转换为 屏幕坐标(二维)
- 字符串匹配
- leetCode#172 Factorial Trailing Zeroes
- 摇摇开门:从营销角度去论述怀才不遇
- CentOS 6使用本地光盘做yum源(tech-life 测试过可用)
- 赖较砍屑抠脚貉磐队墩
- C++ char*,const char*,string的相互转换
- 编程之美系列之寻找最大的K个数
- Day22-进度条对话框
- 单例模式