传统的字符串匹配
1.思路:
重头开始,依次将主串与次串相比较。如果相同则比较主串与次串的下一个字符;如果不同,则回溯至之前主串比较的后一个字符,再与次串进行一对一比较,直至主串比完。
2.代码实现:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
char name1[100] = {"abababdcd"};
char name2[100] = {"ababd"};
int len1 = strlen(name1);
int len2 = strlen(name2);
int ding1 = 0;
int ding2 = 0;
while(ding1 < len1 && ding2 < len2){
if(name1[ding1] == name2[ding2]){
++ding1;
++ding2;
}else{
ding1 = ding1-ding2+1;
ding2 = 0;
}
}
if(ding2 == len2){
printf("YES\n");
}else printf("NO\n");
return 0;
}
模式匹配的改进算法——KMP
1.思路:
在模式匹配中,我们是在匹配到不相同时,回溯到了之前开始匹配的后一位,然后再次进行匹配,时间复杂度能达到0(m*n),这其中我们做了很多的重复操作,在我们比较后,如果不匹配,我们之前比较过的字符没有被利用,在下次比较中又会比较一次,而KMP算法就是优化了这一过程,利用好已经得到的“部分匹配”使子串尽可能的向右移。而在右移后当前的主串字符就能直接和子串的某一位进行比较(也就是对于主串来说就没有回溯了)。
在模式匹配里,‘a’与’d’不匹配后,子串后移一位,又从’b’开始比较。
主串 | a | b | a | b | a | b | d | c | b |
---|---|---|---|---|---|---|---|---|---|
子串 | a | b | a | b | d |
主串 | a | b | a | b | a | b | d | c | b |
---|---|---|---|---|---|---|---|---|---|
子串 | a |
而实际上,我们知道“abab”这一段我们是已经比较过的,我们通过这一段的比较能很容易得出子串可后移的到的位置
主串 | a | b | a | b | a | b | d | c | b |
---|---|---|---|---|---|---|---|---|---|
子串 | a | b |
对于“abab”来说,“ab”是它的最长的“以开头为起始的字符串”与“以末尾为终止的字符串”相等的字符串(不包括本身)。如在“aba”中就为“a”,长度为1;在“abac”中没有,长度为0;在“abcab”中为“ab”长度为2。
当我们找到了这样的字符串后,我们就能在满足不找漏的同时将子串向右移动最大的距离,因为我们找的就是最长的相同字符串,下一个子串和主串一一对应的地方一定在这。
这样我们先把子串在不同长度下的最长相同字符串(头,尾)找出,再进行一次对主串的遍历就可以了。
2.代码实现:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
char name1[10] = {"abababdcd"};
char name2[10] = {"ababd"};
int len1 = strlen(name1);
int len2 = strlen(name2);
int ding1 = 0;
int ding2 = 0;
int next[10];//我们用next数组来存储不匹配时,当前字符应该对应的子串的位置。
void GetNext()
{
int i = 0;
int k = -1;
next[0] = -1;
while(i < len2){
if((k == -1) || (name2[i]==name2[k]))
next[++i] = ++k;
else
k = next[k];
}
}
int main()
{
GetNext();
while(ding2 < len2){
while(ding2 != -1 && name1[ding1] != name2[ding2]){
ding2 = next[ding2];
}
ding1++;
ding2++;
}
if(ding2 == len2){
printf("YES\n");
}else printf("NO\n");
return 0;
}