深入串的模式匹配算法(普通算法和KMP算法)的详解
串的定位操作通常称作串的模式匹配,是各种处理系统中的最重要操作之一。
模式匹配最朴素的算法是回溯法,即模式串跟主串一个字符一个字符的匹配,当模式串中跟主串不匹配时,主串回溯到与模式串匹配开始的下一个位置,模式串回溯到第一个位置,继续匹配。算法的时间复杂度为O(m*n),算法如下:
//朴素的串的模式匹配算法,S为主串,T为模式串,即找S中有没有与T相同的字串
int Index(char *S, char *T, int pos)//pos记录从哪一位开始匹配可以直接用0代替
{
int i=pos, j=0;
while(i <strlen(S) && j <strlen(T))//确保未超出字符串的长度
{
if (S[i] == T[j])
{ ++i; ++j;} //如果相同,则继续向后比较
else
{i = i-j+1; j =0;} //如果不同,就回溯,重新查找
}
if (j == strlen(T))
return i-strlen(T); //若匹配成功,返回S中与T字符串相同开始位置的索引
else return 0; //若匹配不成功,返回0
}
O(m*n)的时间复杂度有点大,于是人们发现了KMP算法,核心思想是:当不匹配发生时,主串不回溯,模式串回溯到“合适”的位置,哪个位置合适,只与模式串有关,所以可以先算出模式串中各个字符,当不匹配发生是,应该回溯到哪个位置。算法整体时间复杂度O(m+m)。
算法如下:
void GetNext(char* T, int *next)
{
int i=1,j=0;
next[1]=0;
while( i < strlen(T) )
{
if (j == 0 || T[i] == T[j])
{
++i; ++j;
next[i] = j;
}
else j = next[j];
}
}
int KMP(char* S, char* T, int pos)
{
int i = pos, j = 1;
while (i)
{
if (S[i] == T[j])
{
++ i; ++ j;
}
else
j = next[j];
}
if (j > strlen(T))
return i-T[0];
else
return 0;
}
求next的操作不是最优的,因为他没有考虑aaaaaaaaaaaaaaaaaaab的情况,这样前面会出现大量的1,这样的算法复杂度已经和最初的朴素算法没有区别了。所以稍微改动一下:
void GetNextEx(char *T, int *next)
{
int i=1,j=0; next[1] = 0;
while(i < strlen(T))
{
if (j == 0 || T[i] == T[j])
{
++i; ++j;
if (T[i] == T[j])
next[i] = next[j]; //减少回退次数
else next[i] = j; //和上面算法一样next[i]=j
}
else j = next[j];
}
}
上一篇:如何求连续几个数之和的最大值
栏 目:C语言
本文标题:深入串的模式匹配算法(普通算法和KMP算法)的详解
本文地址:https://www.xiuzhanwang.com/a1/Cyuyan/4412.html
您可能感兴趣的文章
- 04-02c语言的正则匹配函数 c语言正则表达式函数库
- 04-02c语言中对数函数的表达式 c语言中对数怎么表达
- 04-02C语言中怎么打出三角函数 c语言中怎么打出三角函数的值
- 01-10c语言求1+2+...+n的解决方法
- 01-10求子数组最大和的解决方法详解
- 01-10深入理解约瑟夫环的数学优化方法
- 01-10深入二叉树两个结点的最低共同父结点的详解
- 01-10数据结构课程设计- 解析最少换车次数的问题详解
- 01-10c语言 跳台阶问题的解决方法
- 01-10如何判断一个数是否为2的幂次方?若是,并判断出来是多少次方
阅读排行
本栏相关
- 04-02c语言函数调用后清空内存 c语言调用
- 04-02func函数+在C语言 func函数在c语言中
- 04-02c语言的正则匹配函数 c语言正则表达
- 04-02c语言用函数写分段 用c语言表示分段
- 04-02c语言中对数函数的表达式 c语言中对
- 04-02c语言编写函数冒泡排序 c语言冒泡排
- 04-02c语言没有round函数 round c语言
- 04-02c语言分段函数怎么求 用c语言求分段
- 04-02C语言中怎么打出三角函数 c语言中怎
- 04-02c语言调用函数求fibo C语言调用函数求
随机阅读
- 01-10delphi制作wav文件的方法
- 08-05织梦dedecms什么时候用栏目交叉功能?
- 04-02jquery与jsp,用jquery
- 08-05DEDE织梦data目录下的sessions文件夹有什
- 01-11Mac OSX 打开原生自带读写NTFS功能(图文
- 01-10C#中split用法实例总结
- 08-05dedecms(织梦)副栏目数量限制代码修改
- 01-10SublimeText编译C开发环境设置
- 01-10使用C语言求解扑克牌的顺子及n个骰子
- 01-11ajax实现页面的局部加载