字符串及其匹配方法
一、字符串基本概念
字符串是由零个或多个字符构成的有限序列,一般可表示为如下形式:"C1C2C3C4......Cn" (n>=0)
串中所含字符的个数n称为字符串的长度。当n=0时,字符串为空串。
字符串结束标识符:' \0 '
二、基本函数
求字符串的长度
int length(char str[] ){
char*p=str;
int len=0;
while((*p)!='\0'){
p++;len++;
}
return len;
}
三、模式匹配——BF算法
基本思想
从主串T的第一个字符开始和模式串P的第一个字符进行比较,若相等,则继续比较两者的后续字符;否则,从主串的第二个字符开始和模式P的第一个字符进行比较,重复上述过程,直到P的字符串全部比较完,则说明匹配成功;或者T中的字符全部比较完,则说明匹配失败。
时间复杂度分析:
最好情况:不成功的匹配都发生在匹配串的第一个字符。
假设主串有n个字符,匹配串有m个字符,匹配成功发生在主串的第i个位置上(i从0开始)。则有i-1次不成功和1次成功,不成功中的匹配次数为i-1,成功的匹配次数为m。总共匹配次数=匹配失败花费次数+匹配成功花费次数=i-1+m。所有匹配成功的情况共有n-m+1种。将这n-m+1种情况的匹配次数加权求平均。即可得到时间复杂度为=O(n+m)
最坏情况:不成功的匹配都发生在匹配串的最后一个字符。
同理,在i-1次不成功的匹配中共比较了 (i-1)*m次,第i次成功的匹配中比较了m次,总共比较了i*m次。经过加权求平均后得到时间复杂度=O(m*n)
代码实现
int BF_match(char str[],char s[]){
int i,j,success; //success是匹配成功的标志
i=j=success=0; //i扫描正文,j扫描模式串
int str_len=length(str);
int s_len=length(s);
//主串剩余长度不小于匹配串 && 之前没匹配成功
while((i<=str_len-s_len) && (!success)){
j=0;success=1;
//遍历模式串,遇到不相等字符将success置0,跳出当前while循环,然后i++,从主串的下个字符开始遍历
while((j<=s_len-1) && success){
if(str[i+j]==s[j])
j++;
else
success=0;
}
i++;
}
if(success)
return i-1;
else
return -1;
}
四、KMP算法(快速模式匹配算法)
1.KMP算法基本概念
此算法可以在O(m+n)的时间量级上完成串的模式匹配算法。
通过引入next[]向量,使匹配串在与主串"失配"时,向右滑动更远的距离,减少模式串和主串不必要的匹配次数。从而提高效率。
基本步骤:
(1)求得模式串的next[]数组。
(2)令i,j初始值为0。
(3)若主串第i个字符等于模式串第j个字符,即Ti=Pj。i和j分别加1。
(4)否则,i不变,j=next[ j ]。
(5)若next[ j ]=-1,则从主串下一个位置重新与模式串第一个字符匹配。i++,j=0。
2.next数组
next数组求法:
next数组代码:
void get_next(char str[],int next[]){
int i=0,j=-1;
next[0]=-1;
int str_len=length(str);
while(i<str_len){
if(j==-1 || str[i]==str[j]){
i++;j++;
next[i]=j;
}
else
j=next[j];
}
//打印next数组
for(i=0;i<str_len;i++)
printf("%d ",next[i]);
}
3.Kmp函数代码
int Kmp(char str[],char s[],int next[]){
int i=0,j=0;
int str_len=length(str);
int s_len=length(s);
while(i<str_len && j<s_len){
if(j==-1 || str[i]==s[j]){
i++;j++;
printf("i=%d*j=%d\n",i,j);
}
else
j=next[j];
}
if(j==s_len){
if(s_len==0) //模式串为空串,匹配成功
return -2;
else //正常匹配成功
return i-s_len;
}
else //匹配失败
return -1;
}
(○` 3′○) 感谢观看,希望对你有帮助!