串的匹配模式 蛮力匹配 KMP匹配

BF模式匹配算法
     BF算法Brute-Force算法(蛮力算法),从主串的第pos个字符开始和模式串第1个字符比较,若相等继续比较后续字符,若不相等则回溯到主串第pos+1个字符开始重新比较
      算法描述1.
#define max 20
typedef struct
{
    char ch[max+1];//从1开始存储
    int len;//字符串长度
 }sstring;

int index(sstring *s,int pos,sstring *t)//从一存储
{
    int i,j,k;
    int m=s->len,n=t->len;
    if(pos<1||pos>s->len)
    return 0;
    for(i=pos;i<=m;i++)
    {
        k=i;
        for(j=1;j<=n;j++)
        if(s[k]==t[j])
        k++;
        if(j==n) break;
    }
    return i-j;//返回位置
}
算法描述2.
#define max 20
typedef struct
{
   char ch[max+1];//从1开始存储
   int len;//字符串长度
}sstring;

int index(sstring *s,int pos,sstring *t)//从一存储
{
    int i=pos,j=1;
    if(pos<1||pos>s->len)
    return 0;
    while(i<=s->len&&j<=t->len)//判断条件 while循环一层循环
    {
        if(s->ch[i]==t->ch[j])//相同则继续比较
        {
            i++;j++
        }
        else
        {
            i=i-j+2;//主串回溯到i-j+2(即i的下一个字符)重新比较
            j++;//模式串回到1
        }
    }
    return i-t->len;//返回位置
}




KMP模式匹配算法
KMP算法的不同点在于消除BF算法中的主串s回溯的情况,只需要把模式串尽可能的向右滑动

若主串与模式串存在以下关系
S=S1S2... S i-j+1 S i-j+2... S i-k+1... S i-1 S i... S n
                                                       !=   //Si!=Tj               Si!=Tj 时找到Tk-1=Tj-1,即Tk接下来与主串的Si比较
T=        T1  T2T3 .... Tj-k+1....Tj-1Tj
                                                      !=    //Tj!=Tk
T=                            T1....Tk-1Tk

next算法只与模式串有关与主串无关
令next[j]=k,即当模式串中第j个字符与主串相应字符“失配”时,在模式串中需重新与该主串相应字符比较的位置
next[j]= 0  当j=1时,即第一个字符就"失配",此时向右滑动一个位置即为模式串第一个字符 
next[j]=max{ k |1<k<j且' Tj-k+1....Tj-1Tj '=' T1....Tk-1Tk '} 此集合不为空时
next[j]= 1 其他情况 比如当j=2时,没有1<k<j的值,所以next[j]=1;
next[j]等于'T1....Tj-1'的真前缀字串与真后缀字串相等时的最大长度+1

next算法描述
void Get_next(sstring *t,int *next)
{
    int j=1,k=0;
    next[1]=0;
    while(j<t->len)
    {   
        if(k==0||t->ch[k]==t->ch[j])//k=0,k相当于前缀字符串的位置,j相当于后缀字符串的位置
        {
            k++; //k=0他们相等时(即相当于真前缀字串和真后缀字串相等),那么j++与主串相应字符不等时则让k++与之相比
            j++;
            next[j]=k;
        }
        else k=next[k]; //若当模式串第k个字符和第j个字符不等时,找到第k个字符的next值,继续与第j个字符比较
    }
}
若在匹配过程中Si =Tj ,则i++,j++,继续比较;否则j退回到next[j]继续与Si比较,若相等i++,j++,否则j继续退回到下一个next[j]的位置,这样会出现两种情况:一种是
                            j退回到某个next值(next[next[···next[j]]])继续与主串相应字符比较,另一种是j最终退回到0的位置(主串和模式串字符都向右滑动一个字符)

nextval函数
     nextval函数在next函数上改进,例如主串为'aaabaaaab'模式串为'aaaab'时(next[1,2,3,4,5]={0,1,2,3,4}),  当主串的第4个字符b与模式串的第4个字符不等时还需要将b与a比较3次,而实际上只需要将模式串向右移4位据可以了,因此当主串字符i不等于模式串字符j并且模式串字符j等于模式串字符next[j]时,模式串字符i直接跳过与next[j]比较,直接与nextval[j](next[next[j...]]一直到不相等为止)比较
void Get_nextval(sstring *t,int *next,int *nextval)
{
    int j=2,k;
    nextval[1]=0;//当第一个不相等时像next一样,主串与模式串向右移一位
    while(j<=t->len)
    {
        k=next[j];//记录j的next值
        if(t->ch[k]==t->ch[j])//如果j位置与k位置的字符相等时,下一次比较主串和模式串直接跳过k,找到k的nextval值相比较 
        nextval[j]=nextval[k];
        else nextval[j]=next[k]; //如果不相等则直接比较next的值
        j++;
    }
}


KMP算法描述
typedef struct
{
   char *ch;//从1开始存储
   int len;//字符串长度
}sstring;

int index(sstring *s,int pos,sstring *t)//从一存储
{
    int i=pos,j=1,*next;
    if(pos<1||pos>s->len)
    return 0;
    next=(int*)malloc((t->len+1)*sizeof(int)); //为next数组分配空间,存储每个模式串字符应该访问的位置
    nextval=(int*)malloc((t->len+1)*sizeof(int));
    Get_next(t,next);
    Get_nextval(t,next,nextval);
    while(i<=s->len&&j<=t->len)
    {
        if(j==0||s->ch[i]==t->ch[j])//j==0,j退回到0(即模式串与主串相应字符不等,模式串与主串下一个字符比较)
        {                          //字符相等继续比较
            i++;j++;
        }
        else j=nextval[j];//模式串向右滑动,下一个模式串字符串与相应主串字符比较
    }
    if(j>t->len) return i-t->len;
    else return 0;
}























  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值