数据结构 字符串比较 KMP算法
2009-07-30 13:51
218 查看
KMP算法:最简单的字符串匹配算法由于需要回溯查找,时间复杂度大。而改进型的KMP算法充分利用字符串的特性,减少了主字符串回溯需要查找的时间,大大的降低了其复杂度,大小为O(n+m),n为主字符串长度,m为从字符串长度。
下面介绍下KMP算法的步骤:
主字符串:aabbdcacaabca 从字符串:aabca
首先要设定指向主和从的指针i,j.KMP算法规定主指针不能回头,即网前移动后不能倒回去寻找匹配字符,那么就根据这个规定我们看下有什么变化和要求。
1.首先aabbdcacaabca的第一位和aabca的第一位比较,如果相等i和j都跳到下一位比较,如果不等,i不变j调到前一位比较直到找到相等的。
2.同步骤1,比较了i=2和i=3
3.当i=3时发现c!=b,这时让从串回溯,看3.1后的演示:
3.1由于i不能动,现在我们也不知道j应该在哪个值可行,那只有一个一个试。
考虑从j-1位置依次往从字符串首靠比较合理。发先j=2处,a != b,因为只要一个不
匹配,说明主串对应的段绝对不会与字串匹配。因此移动j-1位继续移动。
3.2这时j=2,发现也不匹配。
3.3这时j=1,发现也不匹配,现在的从串数据都比较完了,
那么这时i和j都跳到下一位比较。
4这时两者有从头开始比较
从上面3发现 c!=b后,有没有未卜先知的功能让从字符串的比较一下子
跳到步骤4,而省去3.1,3.2和3.3这样的累赘,不就轻松很多。呵呵,
(^_^)我们的大师K,M和P就想出了省力讨好偷懒的办法
这个值怎么算到让j一下子跳到哪个位置还是有点复杂。
1. 首先规定第一个位置为0,0代表的意思是在这个位置的从字符和主字符串都
不匹配,两者都跳到下一个位置达到从来!比如从字符串的第一个a,如果主不是的a话那么他们都跳到下一个位置比较。
当next大于0时,它的意义就是,主字符串的指针不变,从的字符串调到对应的next值位与主字符串现在的位置做比较。比如主是aadcef,从是aabca, 从的next值是aabca.其中从b的对应next值为2,也就是说当比较到b这位不匹配时,从应回溯到从2对应的位置上与主进行比较,即从的第二个a上面。
2. 第1位匹配,假如第2位不匹配时,发现第1位a和
第2位a一样的值,那么next也一样。
3. 如果第3位不匹配,因为2位和3位不一样,当3不行的时候,可以把
2位移过来,且第1位与主字符串完全匹配。
4.第4位不匹配时,同上可得。
5.第5位不匹配时,按同样的方法。
说个一般性规律,还真不好说,我现在只是意会到了,言传太难了!!!
详细请看源代码:
下面介绍下KMP算法的步骤:
主字符串:aabbdcacaabca 从字符串:aabca
首先要设定指向主和从的指针i,j.KMP算法规定主指针不能回头,即网前移动后不能倒回去寻找匹配字符,那么就根据这个规定我们看下有什么变化和要求。
1.首先aabbdcacaabca的第一位和aabca的第一位比较,如果相等i和j都跳到下一位比较,如果不等,i不变j调到前一位比较直到找到相等的。
i=1 | ||||||||||||
a | a | b | b | d | c | a | c | a | a | b | c | a |
a | ||||||||||||
j=1 |
i=3 | ||||||||||||
a | a | b | b | d | c | a | c | a | a | b | c | a |
a | a | b | ||||||||||
j=3 |
i=4 | ||||||||||||
a | a | b | b | d | c | a | c | a | a | b | c | a |
a | a | b | c!=b | |||||||||
j=4 |
考虑从j-1位置依次往从字符串首靠比较合理。发先j=2处,a != b,因为只要一个不
匹配,说明主串对应的段绝对不会与字串匹配。因此移动j-1位继续移动。
i=4 | ||||||||||||
a | a | b | b | d | c | a | c | a | a | b | c | a |
a | a | b | ||||||||||
j=3 |
i=4 | ||||||||||||
a | a | b | b | d | c | a | c | a | a | b | c | a |
a | a | |||||||||||
j=2 |
那么这时i和j都跳到下一位比较。
i=4 | ||||||||||||
a | a | b | b | d | c | a | c | a | a | b | c | a |
a | ||||||||||||
j=1 |
i=5 | ||||||||||||
a | a | b | b | d | c | a | c | a | a | b | c | a |
a | ||||||||||||
j=1 |
跳到步骤4,而省去3.1,3.2和3.3这样的累赘,不就轻松很多。呵呵,
(^_^)我们的大师K,M和P就想出了省力讨好偷懒的办法
这个值怎么算到让j一下子跳到哪个位置还是有点复杂。
1. 首先规定第一个位置为0,0代表的意思是在这个位置的从字符和主字符串都
不匹配,两者都跳到下一个位置达到从来!比如从字符串的第一个a,如果主不是的a话那么他们都跳到下一个位置比较。
当next大于0时,它的意义就是,主字符串的指针不变,从的字符串调到对应的next值位与主字符串现在的位置做比较。比如主是aadcef,从是aabca, 从的next值是aabca.其中从b的对应next值为2,也就是说当比较到b这位不匹配时,从应回溯到从2对应的位置上与主进行比较,即从的第二个a上面。
主 | b | ||||
从 | a | a | b | c | a |
1 | |||||
next | 0 |
第2位a一样的值,那么next也一样。
主 | a | b | |||
从 | a | a | b | c | a |
2 | |||||
next | 0 | 0 |
2位移过来,且第1位与主字符串完全匹配。
主 | a | a | c | ||
从 | a | a | b | c | a |
3 | |||||
next | 0 | 0 | 2 |
主 | a | a | b | b | |
从 | a | a | b | c | a |
4 | |||||
next | 0 | 0 | 2 | 1 |
主 | a | a | b | c | c |
从 | a | a | b | c | a |
5 | |||||
next | 0 | 0 | 2 | 1 | 0 |
详细请看源代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> //计算nextValue的值 //其中不明白的地方是 int getNext( const char t[], int next[] ) { unsigned int i,j; i = 1; next[1] = 0; //第一个必定为0 j = 0; while( i < ( strlen( t )+1 ) ) { if( j==0 || ( ( j > 0 ) && ( t[i-1] == t[j-1] ) ) ) { i++; j++; if( t[i-1] != t[j-1] ) { next[i] = j; } else { next[i] = next[j]; } } else { j = next[j]; } } return 1; } int main( void ) { char *s = "aavnsghsabc"; //随机设置字符串 char *t = "abaabcac"; int t_len, s_len; int pos=-1; int i,j,k; int *next; t_len = strlen( t ); s_len = strlen( s ); next = ( int * )malloc( sizeof( int ) * ( t_len+2 ) ); getNext( t, next ); //计算出从字符串的nextValue值 for( j = 0; j < t_len+1; j++ ) next[j] = next[j+1]; //将nextValue值平移到从数组0开始位置 i = 0; j = 0; while( i < (s_len+1 ) && j < ( t_len+1 ) ) {//寻找相匹配的位置 if( s[i] == t[j] ) { i++; j++; } else { k = next[j]; if( k == 0 ) { j++; i++; } else { j = k - 1; } } if( t[j] == '/0' ) pos = i - j + 1; } if( pos > 0 ) { printf( "在%d的个位置找到相同的字符串/n", pos ); } else { printf( "没有找到相匹配的字符串/n" ); } if( next ) free( next ); return 0; }
相关文章推荐
- 【python】python数据结构(三)——字符串:KMP算法的实现
- 数据结构示例之字符串比较
- 数据结构笔记--通过与BF算法的比较理解KMP算法
- 数据结构专项练习--字符串KMP算法3.2
- 几种C#框架提供的数据结构对以字符串为主键的单值查找的效率比较
- KMP算法(通俗易懂的字符串比较算法)
- c++ 数据结构 字符串的自定义类 (文章最后解释了KMP算法)
- jsp中 java字符串比较用equals,不能用==
- 算法与数据结构面试题(19)-统计字符串中的字符个数
- KMP算法字符串模式匹配
- 字符串比较
- javascript中0和空字符串在==和===的情况下的比较
- Character 比较注意先要转换成字符串类型
- java字符串的比较总结
- KMP算法应用------求解一个字符串的最长重复子串
- Linux Shell数值比较和字符串比较及相关
- 比较前N个字符串大小 strncmp
- ajax返回字符串,前台页面比较为false
- 汇编语言: 试编写一段程序,要求比较两个字符串 string1 和 string2 所含字符是否相等,如相 等则显示“MATCH”, 若不相同则显示“NO MATCH”。
- Sql Server中三种字符串合并方法的性能比较