KMP算法中next数组的计算

GetNext的个人理解:

首先先说一下next串的定义吧:


在对于字符串t中每个字符t[j](0<=j<=len-1),存在一个整数k(k使得模式串t

开头的k个字符依次与t[j]的前面的k个字符相同。

#include"顺序串.cpp"//关于顺序串的基本操作,下边放有源代码
void GetNext(SqString t,int next[])//求字符串t的next数组
{
    int j,k;
    j=0;
    k=-1;//j扫描t,k记录t[j]之前于t开头相同的字符个数
    next[0]=-1;
    while(j=t.len)
        return (i-t.len);
    else
        return (-1);
}
int main()
{
    char a1[]="aaaaaaxyzaaaa",a2[]="ababc";
    SqString s1,s2;
    StrAssign(s1,a1);
    StrAssign(s2,a2);
    //cout<

关于顺序串的基本操作。

#include
#include
#include
#define MaxSize 100
using namespace std;
typedef struct
{
    char data[MaxSize];
    int len;
} SqString;
void StrAssign(SqString &str,char cstr[])//将一个字符串常量赋给串str,即生成一个其值等于cstr的串s。
{
    int i;
    for (i=0; cstr[i]!='\0'; i++)
        str.data[i]=cstr[i];
    str.len=i;
}
void StrCopy(SqString &s,SqString t)  //将串t复制给串s
{
    int i;
    for (i=0; istr*/
        str.data[i]=s.data[i];
    for (i=0; istr*/
        str.data[s.len+i]=t.data[i];
    return str;
}
SqString SubStr(SqString s,int i,int j)//返回串s中从第i(1≤i≤StrLength(s))个字符开始的、由连续j个字符组成的子串。
{
    SqString str;
    int k;
    str.len=0;
    if (i<=0 || i>s.len || j<0 || i+j-1>s.len)
    {
        printf("参数不正确\n");
        return str;    /*参数不正确时返回空串*/
    }
    for (k=i-1; kstr*/
        str.data[k-i+1]=s.data[k];
    str.len=j;
    return str;
}

SqString InsStr(SqString s1,int i,SqString s2)//将串s2插入到串s1的第i个字符中,即将s2的第一个字符作为s1的第i个字符,并返回产生的新串
{
    int j;
    SqString str;
    str.len=0;
    if (i<=0 || i>s1.len+1)  /*参数不正确时返回空串*/
    {
        printf("参数不正确\n");
        return s1;
    }
    for (j=0; jstr*/
        str.data[j]=s1.data[j];
    for(j=0; jstr*/
        str.data[i+j-1]=s2.data[j];
    for (j=i-1; jstr*/
        str.data[s2.len+j]=s1.data[j];
    str.len=s1.len+s2.len;
    return str;
}
SqString DelStr(SqString s,int i,int j)//从串s中删去第i(1≤i≤StrLength(s))个字符开始的长度为j的子串,并返回产生的新串。
{
    int k;
    SqString str;
    str.len=0;
    if (i<=0 || i>s.len || i+j>s.len+1)
    {
        printf("参数不正确\n");
        return str;   /*参数不正确时返回空串*/
    }
    for (k=0; kstr*/
        str.data[k]=s.data[k];
    for(k=i+j-1; kstr*/
        str.data[k-j]=s.data[k];
    str.len=s.len-j;
    return str;
}
SqString RepStr(SqString s,int i,int j,SqString t)//在串s中,将第i(1≤i≤StrLength(s))个字符开始的j个字符构成的子串用串t替换,并返回产生的新串
{
    int k;
    SqString str;
    str.len=0;
    if (i<=0 || i>s.len || i+j-1>s.len)
        /*参数不正确时返回空串*/
    {
        printf("参数不正确\n");
        return str;
    }
    for (k=0; kstr*/
        str.data[k]=s.data[k];
    for (k=0; kstr*/
        str.data[i+k-1]=t.data[k];
    for(k=i+j-1; kstr*/
        str.data[t.len+k-j]=s.data[k];
    str.len=s.len-j+t.len;
    return str;
}
void DispStr(SqString s)//输出串s的所有元素值
{
    int i;
    if (s.len>0)
    {
        for (i=0; i

KMP算法的优化nextval[]:

void GetNextval(SqString t,int nextval[])
{
    int j=0,k=-1;
    nextval[0]=-1;
    while(j

书上代码的思路:

当找第j个字符时,考虑t[j]是否与t[next[j]]相等,(next数组中存储的是相同的字符的个数,同时这个数在数值上是与{相等字符个数后一个字符的下标}所相等的)

每一个tnext值都是与前一位的存储相关联,所以要与前一位的t[k]的字符进行比较。

if相等:

j++,k++;

next[j]=k;

j++(因为next中位置的数据信息存储在j+1的位置上)

k++(因为比较字符相同,所以只需要在前者的k+1即可)

else不相等:

K回退

找到0~k个字符“大串中”,找到已经匹配好的“小串”,若找到与t[j]相等的字符,

则把“当前”的k+1存入。若找不到,则此时的k一定回溯到了k=(-1);k++j++

此时t[j]nextnext[j+1]=-1+1=0;正好为0,没有相同的字符串。

由此也就解释了为何要将next[0]=-1。(可能有疑惑为什么小串的数值一定是匹配好的。::因为小串是在大串中的,而我们找的大串就是匹配好的大串,所以小串数值一定也是匹配好的)

    (emmmm:当找不到相同的字符时,k=-1k++,j++k=0,正好符合0个字符与开头字符相同。存储在next[j+1]中,即next[j+1]=0j的数据信息)

    nextval优化的特点就是将失配的字符于此时next[]的值下的字符进行比较,若想等则直接递推,即nextval[j]=nextval[k];因为这两个字符串是相等的再与主串匹配时同样会失配。(当不相等时,则与next的赋值一样,另nextval[j]=k);例如A=C,C=C1,所以A=C1.所以相等时可直接跳过一次不必要的回溯,此优化是在next中进行的优化,优化结果为新的数组nextval[].

    在这里我提供一种方便记忆的方法:1) t[j]!=t[k],nextval[j]=next[j];

                    2) t[j]==t[k],nextval[j]=nextval[k];

                    即:不相等,不变。相等,继承。

 时间关系没有细写,我会再次完善本篇文章。

你可能感兴趣的:(数据结构算法)