字符串模式匹配算法
来源:互联网 发布:mac网络诊断isp失败 编辑:程序博客网 时间:2024/05/16 04:36
1、朴素的模式匹配算法:用两个指针(数组角标)分别指向主串和子串,当字符相等时,指针(角标)都加一,否则,都退回到适当的位置,直到找到子串在主串中出现的位置为止。算法实现如下:
//返回子串t在主串s中第pos个位置的字符开始之后的位置,若不存在,则函数值返回-1// 0<=pos<=strlen(s)-1int index(char *s,char *t,int pos){ int len1 = strlen(s); int len2 = strlen(t); int i = pos;//i从pos位置开始,是主串s的下标 int j = 0;//j用于子串t中当前位置的下标 while(i<len1 && j<len2) { if (s[i] == t[j]) { i++; j++; } else { //i和j都回退 i = i-j+1; j = 0; } } if (j == len2) { return i-len2; } else { return -1; }}
2、KMP模式匹配算法:它是对朴素模式匹配算法的优化,用两个指针(数组角标)分别指向主串和子串,当字符相等时,指针(角标)都加一,否则,指向主串的指针或角标不变,而指向子串的指针或角标退回到适当地位置(这些位置存放在一个next数组当中),直到找到子串在主串中出现的位置为止。
这个next数组的长度和子串的长度相同,并且只与子串有关。它可由下面的公式表示:
j是next数组的下标,当j=0时,next[j]=-1;当j=1时,next[j]=0;在其他情况下,计算子串中当前字符之前的前缀串字符和后缀串字符相等的个数,并且前缀串字符不能包含当前字符的前一个字符,后缀串字符不能包含第一个字符。比如”abcabd”,若当前字符是c,则角标j是2,则前缀字符只有a,后缀字符只有b,又不相等,故next[2]=0,当j指向d时,前缀字符有”ab”,后缀串也有”ab”,故最大长度max=2,即next[j]=2.
计算next数组的代码如下:
**方法一:**//通过计算返回子串t的next数组void get_next(char *t,int *next){ int i,j; i = 0; j = -1; next[0] = -1; int len = strlen(t); while (i < len-1) { if (j==-1 || t[i]==t[j])//t[i]表示后缀的单个字符,t[j]表示前缀的单个字符 { ++i; ++j; next[i] = j; } else { j = next[j];//表示j回退的位置,若字符不相同,则j值回溯 } }}**方法二**int main(){ char str[] = "aabaaaca"; int next[8]; next[0] = -1; next[1] = 0; for (int i=2;i<8;++i) { int count = next[i-1]; char *p = str + count; char *s = str + i - 1; if (*p == *s) { count++; } else { while (count>0) { p--; if (*p != *s) { count--; } else { break; } } } next[i] = count; } return 0;}
然后,KMP算法的实现如下:
//返回子串t在主串s中第pos个位置字符开始之后的位置,若不存在,则函数返回值为-1//t非空,0<=pos<=strlen(s)-1int index_kmp(char *s,char *t,int pos){ int len1 = strlen(s); int len2 = strlen(t); assert(pos>=0 && pos<=len1-1); int i = pos; int j = 0; int next[255];//定义一个next数组 get_next(t,next);// get_nextval(t,next);//对t分析,得到next数组 while (i<len1 && j<len2) { if (j==-1 || s[i] == t[j]) { i++; j++; } else { j = next[j];//j退回到合适的位置,i值不变 } } if (j == len2) { return i-len2; } else { return -1; }}
当然,上面的求next数组的方法还可以改进,比如,当主串是”aaaabcde”,子串是”aaaaax”,此时如果按上述算法求出next数组,在字符串匹配过程中会出现较多不必要进行的比较操作,因此要对next函数进行改进。代码如下:
//获取nextval数组,修改的部分加星号表示void get_nextval(char *t,int *nextval){ int i,j; i = 0; j = -1; nextval[0] = -1; int len = strlen(t); while (j<len-1) { if (j==-1 || t[i]==t[j])//t[i]表示后缀字符,t[j]表示前缀字符,i不回退 { i++; j++; ****if (t[i] != t[j])//当前字符与前缀字符不同 { nextval[i] = j; } else//当前字符与前缀字符相同 { nextval[i] = nextval[j]; }**** } else//若前缀字符和后缀字符不相同,j会退到合适的位置 { j = nextval[j]; } }}
总结改进过得KMP匹配算法,它是在计算出next值得同时,如果i位字符与它next值指向的j位字符相等,则该i位的nextval就指向j位的nextval值,如果不等,则该i位的nextval值就是它自己i的next的值。
- 字符串模式匹配算法
- 字符串模式匹配算法
- 字符串模式匹配算法
- 字符串模式匹配算法
- 字符串模式匹配算法
- 字符串模式匹配算法
- 字符串模式匹配KMP算法
- 字符串模式匹配KMP算法
- KMP字符串模式匹配算法
- 字符串模式匹配KMP算法
- KMP字符串模式匹配算法
- KMP字符串模式匹配算法
- 字符串模式匹配KMP算法
- 字符串模式匹配:Sunday算法
- KMP 字符串模式匹配算法
- 字符串模式匹配KMP算法
- 字符串模式匹配KMP算法
- 算法 字符串模式匹配KMP
- centos上配置tomcat服务器
- HDU 5834 树形DP
- poj3278 Catch That Cow
- B 树笔记
- BZOJ 2464: 中山市选[2009]小明的游戏 简单搜索
- 字符串模式匹配算法
- 开源日志记录工具log4j 使用
- Andy's First Dictionary
- 辨析matmul product(一般矩阵乘积),hadamard product(哈达玛积)、kronecker product(克罗内克积)
- C++知识总结(8)
- JavaScript循环语句++
- C++ 编译器的函数名修饰规则
- SQL写入性能优化。
- SQL NULL 函数