KMP和扩展kmp

转载:https://blog.csdn.net/v_july_v/article/details/7041827

查找相同字符串

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int N=100;
int nxt[100];
void GetNextval(char* p)
{
    int pLen = strlen(p);
    nxt[0] = -1;
    int k = -1;
    int j = 0;
    while (j < pLen - 1)
    {
        //p[k]表示前缀,p[j]表示后缀
        if (k == -1 || p[j] == p[k])
        {
            ++j;
            ++k;
            //较之前nxt数组求法,改动在下面4行
        nxt[j] = k;
        }
        else
        {
            k = nxt[k];
        }
    }
}
int kmp(char* s, char* p)
{
    int i = 0;
    int j = 0;
    int sLen = strlen(s);
    int pLen = strlen(p);
    GetNextval(p);
    while (i < sLen && j < pLen)
    {
        //①如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++
        if (j == -1 || s[i] == p[j])
        {
            i++;
            j++;
        }
        else
        {
            //②如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = nxt[j]
            //nxt[j]即为j所对应的nxt值
            j = nxt[j];
        }
    }
    if (j == pLen)
        return i - j;
    else
        return -1;
}

char a[100],b[100];
int main()
{
    while(scanf("%s%s",a,b)!=EOF)
    {
        if(kmp(a,b)!=-1)
            printf("ans= %d\n", kmp(a,b));
        else
            printf("Not find\n");
    }
    return 0;
}



strstr(s1,s2)判断s1中有没有s2有则返回字符没有就返回NULL
exkmp

扩展kmp处理的是:对于一个串T TT,串S SS每个后缀和串T TT的最长公共前缀。

int Next[maxn],extend[maxn];
char s[1000050],t[1000050];

void getNext(char* str){
    int i=0,j,pos,len=strlen(str);
    Next[0]=len;
    while(str[i]==str[i+1]&&i+1<len)i++;Next[1]=i;
    pos=1;
    for(int i=2;i<len;i++){
        if(Next[i-pos]+i<Next[pos]+pos){
            Next[i]=Next[i-pos];
        }
        else{
            j=Next[pos]+pos-i;
            if(j<0)j=0;//如果i比最远的的小,说明得从头开始。
            while(i+j<len&&str[j]==str[j+i])j++;Next[i]=j;
            pos=i;
        }
    }
}

void Exkmp(char* s,char* t){
    int i=0,j,pos,l1=strlen(s),l2=strlen(t);
    getNext(t);
    while(s[i]==t[i]&&i<l1&&i<l2)i++;extend[0]=i;
    pos=0;
    for(int i=1;i<l1;i++){
        if(Next[i-pos]+i<extend[pos]+pos)
            extend[i]=Next[i-pos];
        else{
            j=extend[pos]+pos-i;
            if(j<0)j=0;
            while(i+j<l1&&j<l2&&s[i+j]==t[j])j++;extend[i]=j;
            pos=i;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值