字符串KMP小结

一:返回模式串在主串的下标BF与KMP与KMP1

《字符串KMP小结》

#include <iostream>
#include<malloc.h>
#include<cstdio>
using namespace std;
#define MaxSize 100
int next[MaxSize];
int nextval[MaxSize];
typedef struct
{
    char data[MaxSize];
    int length;
} SqString;
void Assign(SqString &s,char cstr[])
{
    int i;
    for(i=0; cstr[i]!='\0'; i++)
        s.data[i]=cstr[i];
    s.length=i;
}
int BF(SqString s,SqString t)
{
    int i=0,j=0;
    while(i<s.length&&j<t.length)
    {
        if(s.data[i]==t.data[j])
        {
            i++;
            j++;
        }
        else
        {
            i=i-j+1;
            j=0;
        }

    }
    if(j>=t.length)
            return i-t.length;
        else
            return -1;
}
void GetNext(SqString t,int next[])
{
    int i=0,j=-1;
    next[0]=-1;
    while(i<t.length-1)
    {
        if(j==-1||t.data[i]==t.data[j])
        {
            i++;
            j++;
            next[i]=j;
        }
        else
            j=next[j];
    }
}
int KMP(SqString s,SqString t)
{
    int i=0,j=0;
    GetNext(t,next);
    while(i<s.length&&j<t.length)
    {
        if(j==-1||s.data[i]==t.data[j])
        {
            i++;
            j++;
        }
        else
            j=next[j];
    }
    if(j>=t.length)
        return i-t.length;
    else
        return -1;
}
void GetNextVal(SqString t,int next[])
{
    int i=0,j=-1;
    nextval[0]=-1;
    while(i<t.length)
    {
        if(j==-1||t.data[i]==t.data[j])
        {
            i++;
            j++;
            if(t.data[i]!=t.data[j])
                nextval[i]=j;
            else
                nextval[i]=nextval[j];
        }
        else
            j=nextval[j];
    }
}
int KMP1(SqString s,SqString t)
{
    int i=0,j=0;
    GetNextVal(t,next);
    while(i<s.length&&j<t.length)
    {
        if(j==-1||s.data[i]==t.data[j])
        {
            i++;
            j++;
        }
        else
            j=nextval[j];
    }
    if(j>=t.length)
        return i-t.length;
    else
        return -1;
}
int main()
{
    SqString s,t;
    Assign(s,"abcdefghi");
    Assign(t,"cdef");
    printf("用BF算法返回匹配下标:");
    printf("%d\n",BF(s,t));
    printf("用KMP算法返回匹配下标:");
    printf("%d\n",KMP(s,t));
    printf("用修正后的KMP算法返回匹配下标:");
    printf("%d\n",KMP1(s,t));
    return 0;
}

二:返回模式串在主串中出现的次数

如图:

《字符串KMP小结》

#include <iostream>
#include<malloc.h>
#include<cstdio>
using namespace std;
#define MaxSize 100
int next[MaxSize];
int nextval[MaxSize];
int n;
typedef struct
{
    char data[MaxSize];
    int length;
} SqString;
void Assign(SqString &s,char cstr[])
{
    int i;
    for(i=0; cstr[i]!='\0'; i++)
        s.data[i]=cstr[i];
    s.length=i;
}
int BF(SqString s,SqString t)
{
    int i=0,j=0,n=0;
    while(i<s.length&&j<t.length)
    {
        if(s.data[i]==t.data[j])
        {
            i++;
            j++;
        }
        else
        {
            i=i-j+1;
            j=0;
        }
        ///仅仅在此部分做了处理
        
        if(j>=t.length)
        {
            n++;
            i=i-j+1;
            j=0;
        }
    }
    return n;
}
void GetNext(SqString t,int next[])
{
    int i=0,j=-1;
    next[0]=-1;
    while(i<t.length-1)
    {
        if(j==-1||t.data[i]==t.data[j])
        {
            i++;
            j++;
            next[i]=j;
        }
        else
            j=next[j];
    }
}
int KMP(SqString s,SqString t)
{
    int i=0,j=0,n=0;
    GetNext(t,next);
    while(i<s.length&&j<t.length)
    {
        if(j==-1||s.data[i]==t.data[j])
        {
            i++;
            j++;
        }
        else
            j=next[j];
        ///仅仅在此部分做了处理
        if(j>=t.length)
        {
            n++;
            i=i-j+1;
            j=0;
        }
    }
    return n;
}
void GetNextVal(SqString t,int next[])
{
    int i=0,j=-1;
    nextval[0]=-1;
    while(i<t.length)
    {
        if(j==-1||t.data[i]==t.data[j])
        {
            i++;
            j++;
            if(t.data[i]!=t.data[j])
                nextval[i]=j;
            else
                nextval[i]=nextval[j];
        }
        else
            j=nextval[j];
    }
}
int KMP1(SqString s,SqString t)
{
    int i=0,j=0,n=0;
    GetNextVal(t,next);
    while(i<s.length&&j<t.length)
    {
        if(j==-1||s.data[i]==t.data[j])
        {
            i++;
            j++;
        }
        else
            j=nextval[j];
        ///仅仅在此部分做了处理
        if(j>=t.length)
        {
            n++;
            i=i-j+1;
            j=0;
        }
    }
    return n;
}
int main()
{
    SqString s,t;
    Assign(s,"abcdefghicdefcdef");
    Assign(t,"cdef");
    printf("用BF算法返回匹配次数:");
    printf("%d\n",BF(s,t));
    printf("用KMP算法返回匹配次数:");
    printf("%d\n",KMP(s,t));
    printf("用修正后的KMP算法返回匹配次数:");
    printf("%d\n",KMP1(s,t));
    return 0;
}

三:最小循环节,即最大的循环次数

如图:POJ2406

《字符串KMP小结》

len-next[len]是最小循环节,而len/(len-next[len])是最大的循环次数

#include <iostream>
#include<string.h>
#include<cstdio>
using namespace std;
char t[1000000];
int next[1000000];
void getnext()
{
    int i=0,j=-1;
    next[0]=-1;
    while(i<strlen(t))
    {
        if(j==-1||t[i]==t[j])
        {
            i++;
            j++;
            next[i]=j;
        }
        else
            j=next[j];
    }
}
int main()
{
    while(scanf("%s",t))
    {
        if(t[0]=='.')
            break;
        int len=strlen(t);
        getnext();
        if(len%(len-next[len])==0)
            printf("%d\n",len/(len-next[len]));
        else
            printf("1\n");
    }
    return 0;
}

字符串的所有大小循环节以及他们的周期POJ1961

如图:

《字符串KMP小结》

///i-next[i]是循环节的长度

void getnext(const char *t)///有无参数都行

#include <iostream>
#include<string.h>
#include<cstdio>
using namespace std;
char t[1000000];
int next[1000000];
int len;
void getnext(const char *t)///无参数也行
{
    int i=0,j=-1;
    next[0]=-1;
    while(i<strlen(t))
    {
        if(j==-1||t[i]==t[j])
        {
            i++;
            j++;
            next[i]=j;
        }
        else
            j=next[j];
    }
}
int main()
{
    int ant=0;
    while(scanf("%d",&len)&&len)
    {
        scanf("%s",t);
        getnext(t);///无参数也行
        printf("Test case #%d\n",++ant);
        for(int i=1;i<=len;i++)
        {
            if(i%(i-next[i])==0&&(i!=i-next[i])) ///如果有多个循环节
            printf("%d %d\n",i,i/(i-next[i]));
        }
        printf("\n");
    }
    return 0;
}

哈哈



    原文作者:KMP算法
    原文地址: https://blog.csdn.net/a716121/article/details/51140258
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞