13、KMP算法

本文深入探讨了KMP算法的工作原理,详细解释了如何构建失配表,并通过实例展示了如何使用C++和C语言实现该算法。通过阅读,读者将能够理解KMP算法在字符串搜索中的高效性和应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <iostream>
#include <cstring>

using namespace std;
#define MaxSize 255
typedef struct {
    char *ch;
    int len;
}SString;
void Init(SString &str);//初始化串
bool StrAssign(SString & str, char*ch);//赋值操作
bool StrCopy(SString&str,SString T);//复制串
bool IsEmpty(SString str);//判空
int StrCompare(SString s1,SString s2);//串比较操作
bool Concat(SString &s,SString&s1,SString&s2);//串连接
bool SubString(SString str,SString&sub,int pos,int len);//返回指定位置指定长度的字串
bool Clear(SString&str);//清空字符串
bool Destory(SString&str);//销毁字符串
int index(SString &str,SString& t);//定位操作,若主串str和字串t有相同的字串,则返回他在这个主串首次出现的位置
void Print(SString str);//打印


///KMP算法

void GetNext(string t,int next[]);//获取next数组
//NEXT数组
int KmpNext(SString &str,SString& t);//定位操作,若主串str和字串t有相同的字串,则返回他在这个主串首次出现的位置
//NextVal数组
int KmpNextVal(SString &str,SString& t);


int main()
{
    SString  s1;SString s2;
    char* ss1;char* ss2;
    ss1="google";
    ss2="googlogoogle";
    Init(s1);Init(s2);
    StrAssign(s1,ss1);
    StrAssign(s2,ss2);
    cout<<"s1:";
    Print(s1);
    cout<<endl;
    cout<<"s2:";
    Print(s2);
    cout<<endl;
    cout<<KmpNext(s2,s1)<<endl;
    cout<<KmpNextVal(s2,s1)<<endl;
}


void GetNext(SString t,int next[])//获取next数组
{
    int i=1,j=0;
    next[1]=0;
    while(i<t.len)
    {
        if(j==0||t.ch[i]==t.ch[j])
        {
            ++i;++j;
        }
        else
            j=next[j];
    }
}

int KmpNext(SString &str,SString& t)//定位操作,若主串str和字串t有相同的字串,则返回他在这个主串首次出现的位置
{
    int i=1,j=0;
    int next[t.len+1];
    GetNext(t,next);
    while(i<=str.len&&j<=t.len)
    {
        if(j==0||str.ch[i]==t.ch[j])
        {
            i++;j++;
        }
        else
            j=next[j];
    }
    if(j>t.len)
        return i-t.len;
    else
        return 0;

}
int KmpNextVal(SString &str,SString& t)
{
    int i=1,j=0;
    int next[t.len+1];
    GetNext(t,next);
    int nextval[t.len+1];
    nextval[1]=0;
    for(int j=2;j<=t.len;j++)
    {
        if(t.ch[next[j]]==t.ch[j])
            nextval[j]=nextval[next[j]];
        else
            nextval[j]=next[j];
    }
    while(i<=str.len&&j<=t.len)
    {
        if(j==0||str.ch[i]==t.ch[j])
        {
            i++;j++;
        }
        else
            j=nextval[j];
    }
    if(j>t.len)
        return i-t.len;
    else
        return 0;

}









void Init(SString &str)//初始化串
{
    str.ch= nullptr;
    str.len=0;
}


bool StrAssign(SString & str, char*ch)//赋值操作
{
    if(str.ch)
    {
        free(str.ch);
        str.ch=NULL;
    }//释放原空间
    int len=0;
    char*c=ch;
    while(*c)//计算ch串长度
    {
        ++len;
        ++c;
    }
    if(len==0)
    {
        Init(str);
        return false;
    }
    else
    {
        str.ch=(char*)malloc(sizeof(char)*len+1);
        if(str.ch==NULL)return false;//空间分配失败
        else{
            for(int i=0;i<=len;i++)
                str.ch[i]=ch[i];
            str.len=len;
            return true;
        }
    }

}

bool StrCopy(SString&str,SString T)//复制串
{
    str.ch=(char*)malloc(sizeof(char)*(T.len+1));
    for(int i=0;i<=T.len;i++)
    {
        str.ch[i]=T.ch[i];
    }
    str.len=T.len;
    return true;
}

bool IsEmpty(SString str)//判空
{
    return (str.len==0);
}

int StrCompare(SString s1,SString s2)//串比较操作
{
    for(int i=0;i<s1.len&&i<s2.len;i++)
    {
        if(s1.ch[i]!=s2.ch[i])
            return s1.ch[i]-s2.ch[i];
    }
    return s1.len-s2.len;
}

bool Concat(SString &s,SString&s1,SString&s2)//串连接
{
    if(s.ch)
    {
        free(s.ch);
        s.ch=NULL;
    }
    s.ch=(char*)malloc(sizeof(char)*(s1.len+s2.len+1));
    if(s.ch==NULL)return false;//空间分配失败
    else {
        for (int i = 0; i < s1.len; i++) {
            s.ch[i] = s1.ch[i];
        }
        for (int j = s1.len; j <= (s1.len + s2.len); j++)
            s.ch[j] = s2.ch[j - s1.len];
        s.len=s1.len+s2.len;
        return true;
    }

}

bool SubString(SString str,SString&sub,int pos,int len)//返回指定位置指定长度的字串
{
    if(pos<0||pos>=str.len||len<0||pos+len>str.len)
        return false;
    if(sub.ch)
    {
        free(sub.ch);
        sub.ch=NULL;
    }

    if(len==0)
    {
        sub.ch=NULL;
        sub.len=0;
        return true;
    }
    else
    {
        sub.ch=(char*)malloc(sizeof(char)*(len+1));
        for(int i=pos-1,j=0;j<=len;i++,j++)
        {
            sub.ch[j]=str.ch[i];
        }
        sub.len=len;
        return true;
    }

}

bool Clear(SString&str)//清空字符串
{
    if(str.ch)
    {
        free(str.ch);
        str.ch=NULL;
    }
    str.len=0;
return true;

}
bool Destory(SString&str)//销毁字符串
{
    if(str.ch)
    {
        free(str.ch);
    }
    return true;
}
int index(SString &str,SString& t)//定位操作,若主串str和字串t有相同的字串,则返回他在这个主串首次出现的位置
{
    int i=0,j=0;
    if(IsEmpty(t))return -1;
    while(i<str.len&&j<str.len)
    {
        if(str.ch[i]==t.ch[j])
        {
            i++;
            j++;
        }
        else
        {
            i=i-j+1;j=0;
        }
    }
        if(j>=t.len)
            return i-j+1;
        else
            return -1;

}

void Print(SString str)//打印
{
    for(int i=0;i<str.len;i++)
    {
        cout<<str.ch[i];
    }
}


结果在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值