数据结构 · 串

data从0开始存根据KMP算法进行了调整,歪打正着做对了

回头进行分析时遇到了麻烦

存储地址/实际地址 颠来倒去 实在不明白

T1型·数组·固定长度(a[0]起存/半成品/next)

已停止对该代码段的维护

#include <stdio.h>
#include <string.h>
#include <iostream>
typedef struct skr
{
    char data[233]; //定义可容纳233个字符的空间
    int l;          //标记当前实际串长
};

// ABABABBBAAABABAAAABABAAABABAAABABAAABABAA
// ABABAAABABAA
// 011234223456  重叠区T18 (back里存 存储地址,+1后得到实际 第几个元素)
// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab
// aaaaaab
//《功能模块·10种》

void init(skr &a)
{
    memset(a.data, 0, sizeof(a.data));
    a.l = 0;
}
void create(skr &s, char cstr[])
{ //《创建》
    int i;
    for (i = 0; cstr[i] != '\0'; i++)
        s.data[i] = cstr[i];
    s.l = i;
}
void copy(skr &s, skr t)
{ //《复制》
    int i;
    for (i = 0; i < t.l; i++)
        s.data[i] = t.data[i];
    s.l = t.l;
}
bool equal(skr s, skr t)
{ //《相同?》
    bool f = true;
    int i;
    if (s.l != t.l) //长度不相等时返回0
        f = false;
    else
        for (i = 0; i < s.l; i++)
            if (s.data[i] != t.data[i])
            { //有一个对应字符不相同时返回0
                f = false;
                break;
            }
    return f;
}
int len(skr s)
{ //《长度》
    return s.l;
}

skr contact(skr s, skr t)
{ //《合并·双串》
    skr str;
    int i;
    str.l = s.l + t.l;
    for (i = 0; i < s.l; i++) //将s.data[0..s.l-1]复制到str
        str.data[i] = s.data[i];
    for (i = 0; i < t.l; i++) //将t.data[0..t.l-1]复制到str
        str.data[s.l + i] = t.data[i];
    return str;
}
skr take_out(skr s, int i, int j)
{ //《提取·子串·i-->j》
    skr str;
    int k;
    str.l = 0;
    if (i <= 0 || i > s.l || j < 0 || i + j - 1 > s.l)
        return str;                     //参数不正确时返回空串
    for (k = i - 1; k < i + j - 1; k++) //将s.data[i..i+j]复制到str
        str.data[k - i + 1] = s.data[k];
    str.l = j;
    return str;
}
skr insert(skr s1, int i, skr s2)
{ //《插入·i位置·插入·s2》
    int j;
    skr str;
    str.l = 0;
    if (i <= 0 || i > s1.l + 1) //参数不正确时返回空串
        return str;
    for (j = 0; j < i - 1; j++) //将s1.data[0..i-2]复制到str
        str.data[j] = s1.data[j];
    for (j = 0; j < s2.l; j++) //将s2.data[0..s2.l-1]复制到str
        str.data[i + j - 1] = s2.data[j];
    for (j = i - 1; j < s1.l; j++) //将s1.data[i-1..s1.l-1]复制到str
        str.data[s2.l + j] = s1.data[j];
    str.l = s1.l + s2.l;
    return str;
}
skr del(skr s, int i, int j)
{ //《删除·i起删除j个》
    int k;
    skr str;
    str.l = 0;
    if (i <= 0 || i > s.l || i + j > s.l + 1) //参数不正确时返回空串
        return str;
    for (k = 0; k < i - 1; k++) //将s.data[0..i-2]复制到str
        str.data[k] = s.data[k];
    for (k = i + j - 1; k < s.l; k++) //将s.data[i+j-1..s.l-1]复制到str
        str.data[k - j] = s.data[k];
    str.l = s.l - j;
    return str;
}
skr replace(skr s, int i, int j, skr t)
{ //《替换·s中i开始j个·换成t》
    int k;
    skr str;
    str.l = 0;
    if (i <= 0 || i > s.l || i + j - 1 > s.l) //参数不正确时返回空串
        return str;
    for (k = 0; k < i - 1; k++) //将s.data[0..i-2]复制到str
        str.data[k] = s.data[k];
    for (k = 0; k < t.l; k++) //将t.data[0..t.l-1]复制到str
        str.data[i + k - 1] = t.data[k];
    for (k = i + j - 1; k < s.l; k++) //将s.data[i+j-1..s.l-1]复制到str
        str.data[t.l + k - j] = s.data[k];
    str.l = s.l - j + t.l;
    return str;
}

void print(skr s)
{ //《输出·串》
    int i;
    if (s.l > 0)
    {
        printf("%s", s.data);
    }
}
void menu(skr s1, skr s2)
{ //《菜单》
    system("cls");
    printf("S1:   ");
    print(s1);
    printf("   长度:%d\n", len(s1));
    printf("S2:   ");
    print(s2);
    printf("   长度:%d\n", len(s2));
    printf("1-创建s1\t2-创建s2\t3-插入\t4-删除\n");
    printf("5-替换\t\r6-提取\t\t7-连接\t\t8-清空\t9-查找\n");
    printf("请输入您的选择:");
}
bool clear(skr &s)
{ //《清空》
    s = del(s, 1, s.l);
    s.l = 0;
}
int search(skr s1, skr s2, int t)
{ //《查找·相同串》s1更长,s2是子串 复杂度O(n*m)
    int i = t - 1, j = 0;
    printf("\n采用暴力算法!O(n*m)\n");
    // printf("%d %d %d %d\n",s1.l,s2.l,i,j);
    while (i < s1.l && j < s2.l)
    { //主串读取完成·已经发现了子串·则跳出
        if (s1.data[i] == s2.data[j])
        {
            i++;
            j++;
            // printf("i=%d j=%d 相同!  j=%d\n",i-1,j-1,j);
        }
        else
        {
            // printf("i=%d j=%d 不同!",i,j);
            i = i - j + 1;
            j = 0;
            // printf("  i=%d,j=%d\n",i,j);
        }
    } // printf("%d %d %d\n",i,s2.l,i-s2.l);
    if (j == s2.l)
        return i - s2.l + 1; //例如asdqwe123 找qwe,读取到e是i=5,+1后跳出=6,这时候恰好=实际地址(末尾)
    else
        return 0; //此时-3后=3,指向d就不对,因为只需要往右移动2格即可
}
void get_next(skr s2, int t[])
{ //《KMP辅助!由子串生成back数组》
    int x = 1, y = 0, i;
    while (x <= s2.l)
    {
        // printf("x=%d\ty=%d\n", x, y);
        /*for (i = 1; i <= x; i++)
            printf(" ");
        printf("X\n");
        printf("%s\n", s2);
        for (i = 1; i <= y; i++)
            printf(" ");
        printf("Y\n");*/
        if (y == 0 || s2.data[x] == s2.data[y])
        {                 //这里的x y运用是都是存储地址
            t[++x] = ++y; //[]优先级>++(前置也没用,先算再各种++),等价于t[1]=y=0;x++;y++;
            /*if (s2.data[x] == s2.data[y])
                printf("  相同");
            else
                printf("  启封");
            printf("的元素!x、y各+1。t[%d]=%d\n", x - 1, t[x - 1]);*/
        }
        else
        {
            // printf("  不同的元素!y由%d退回到%d\n", y, t[y]);
            y = t[y];
        }
        // printf("/-----------------------------------------/\n");
    }
}
int KMP(skr s1, skr s2, int t)
{ //《查找·相同串》s1更长,s2是子串 KMP算法 复杂度O(n+m)
    printf("\n启用KMP算法!·O(n+m)\n");
    int back[233] = {}, x, y, z;
    get_next(s2, back);
    // t[x]=y;   实际位置x发现异常,则退回到实际位置y(子串指针)
    printf("NEXT情况报备:");
    for (x = 1; x <= s2.l; x++)
        printf("%d ", back[x]);
    printf("\n\n");
    x = t - 1;
    y = 0;
    while (x < s1.l && y < s2.l)
    {
        // printf("x=%d  y=%d", x, y);
        if (y == 0 || s1.data[x] == s2.data[y])
        {
            x++;
            y++;
            /*if (s2.data[x] == s2.data[y])
                printf("相同");
            else
                printf("启封");
            printf("的元素!x、y各+1  .\n");*/
        }
        else
        {
            // printf("不同的元素!将y从%d回溯到%d\n", y, back[y]);
            y = back[y];
        }
    }
    if (y == s2.l)
        return x - s2.l + 1;
    else
        return 0;
} //优点在于不用回溯i指针,而是利用 部分匹配+滑动的机制

int main()
{
    skr s1, s2, s3, s4;
    init(s1);
    init(s2);
    init(s3);
    init(s4);

    int x, y, z;
    char a[233], t;
    while (1)
    {
        menu(s1, s2);
        scanf("%d", &x);
        printf("\n");
        switch (x)
        {
        case 1:
        {                    //《创建s1》
            scanf("%c", &t); //挡住回车键
            gets(a);
            init(s1);
            create(s1, a);
            break;
        }
        case 2:
        { //《创建s2》
            scanf("%c", &t);
            gets(a);
            init(s2);
            create(s2, a);
            break;
        }
        case 3:
        { //《插入·s1s2互插》
            printf("s1,s2,谁是攻?");
            scanf("%d", &x);
            if (x == 1)
            {
                printf("向s2第x个字符插入串s1,输入x:");
                scanf("%d", &x);
                s2 = insert(s2, x, s1);
            }
            else
            {
                printf("向s1第x个字符插入串s2,输入x:");
                scanf("%d", &x);
                s1 = insert(s1, x, s2);
            }
            break;
        }
        case 4:
        { //《删除·可选》
            printf("对谁进行操作:");
            scanf("%d", &x);
            if (x == 1)
            {
                printf("对S%d操作!第x起删除y个:", x);
                scanf("%d%d", &x, &y);
                s1 = del(s1, x, y);
            }
            else
            {
                printf("对S%d操作!第x起删除y个:", x);
                scanf("%d%d", &x, &y);
                s2 = del(s2, x, y);
            }
            break;
        }
        case 5:
        { //《替换》
            printf("谁被替换插入:");
            scanf("%d", &x);
            if (x == 1)
            {
                printf("输入替换的字符段:");
                scanf("%d%d", &x, &y);
                s1 = replace(s1, x, y, s2);
            }
            else
            {
                printf("输入替换的字符段:");
                scanf("%d%d", &x, &y);
                s2 = replace(s2, x, y, s1);
            }
            break;
        }
        case 6:
        { //《提取》
            printf("从哪个串开始提取?从x起共y个?");
            scanf("%d%d%d", &z, &x, &y);
            if (z == 1)
                s3 = take_out(s1, x, y);
            else
                s3 = take_out(s2, x, y);
            printf("捕获子串!  ");
            print(s3);
            printf("\n");
            break;
        }
        case 7:
        { //《连接》
            s3 = contact(s1, s2);
            printf("完成链接!  ");
            print(s3);
            printf("\n");
            break;
        }
        case 8:
        { //《清空》
            printf("清空谁:");
            scanf("%d", &x);
            if (x == 1)
                clear(s1);
            if (x == 2)
                clear(s2);
            break;
        }
        case 9:
        { //《查找·子串》
            printf("谁是主串?从第几个开始查找?是否采用KMP算法?");
            scanf("%d%d%d", &x, &y, &z);
            if (x == 1 && z == 0)
                z = search(s1, s2, y);
            else if (x == 2 && z == 0)
                z = search(s2, s1, y);
            else if (x == 1 && z == 1)
                z = KMP(s1, s2, y);
            else if (x == 2 && z == 1)
                z = KMP(s2, s1, y);
            if (z != 0)
                printf("发现子串!位于%d\n", z);
            break;
        }
        }
        printf("\n");
        system("pause");
    }
    return 0;
}
//  2021/10/07  寂之锋·第七军团·科研攻坚小组(任务:PTA试题全覆盖·数构基础块全覆盖)

T2型·数组·固定长度(a[1]起存/成品/next/nextval)

#include <stdio.h>  //  2021/10/07  寂之锋·第七军团·科研攻坚小组(任务:PTA试题全覆盖·数构基础块全覆盖)
#include <string.h> //测试数据
#include <iostream> //ABABABBBAAABABAAAABABAAABABAAABABAAABABAA
#define max 2745    // ABABAAABABAA
typedef struct skr
{
    char data[max]; //定义可容纳max个字符的空间
};

void get_nextval(skr T, int n[])
{ //《get_nextval》
    int i = 1, j = 0;
    n[1] = 0;
    while (i < T.data[0])
    {
        if (j == 0 || T.data[i] == T.data[j])
        {
            ++i, ++j;
            if (T.data[i] != T.data[j])
                n[i] = j;
            else
                n[i] = n[j];
        }
        else
            j = n[j];
    }
    for (i = 1; i <= T.data[0]; i++)
        printf("%d ", n[i]);
}
void create(skr &s, char cstr[])
{ //《创建》
    int i;
    for (i = 0; cstr[i] != '\0'; i++)
        s.data[i + 1] = cstr[i]; //从1开始存,0存总长度
    s.data[0] = i;
}
bool equal(skr s, skr t)
{ //《相同?》
    bool f = true;
    int i;
    if (s.data[0] != t.data[0]) //长度不相等时返回0
        f = false;
    else
        for (i = 1; i <= s.data[0]; i++)
            if (s.data[i] != t.data[i])
            { //有一个对应字符不相同时返回0
                f = false;
                break;
            }
    return f;
}
int len(skr s)
{ //《长度》
    return s.data[0];
}
skr contact(skr s, skr t)
{ //《合并·双串》
    skr str;
    int i;
    str.data[0] = s.data[0] + t.data[0];
    for (i = 1; i <= s.data[0]; i++) //将s.data[0..s.data[0]-1]复制到str
        str.data[i] = s.data[i];
    for (i = 1; i <= t.data[0]; i++) //将t.data[0..t.data[0]-1]复制到str
        str.data[s.data[0] + i] = t.data[i];
    return str;
}
skr take_out(skr s, int i, int j)
{ //《提取·子串·i后 j个》
    skr str;
    int k;
    str.data[0] = 0;
    if (i <= 0 || i > s.data[0] || j < 0 || i + j > s.data[0] + 1)
        return str;                      //参数不正确时返回空串
    for (k = i; k <= i + j; k++)         //将s.data[i..i+j]复制到str
        str.data[k - i + 1] = s.data[k]; //从1开始存,内容存k=i开始
    str.data[0] = j;
    return str;
}
skr insert(skr s1, int i, skr s2)
{ //《插入·i位置·插入·s2》
    int j;
    skr str;
    str.data[0] = 0;
    if (i <= 0 || i > s1.data[0] + 1) //参数不正确时返回空串
        return str;
    for (j = 1; j <= i - 1; j++) //前i-1个 (共i-1个)
        str.data[j] = s1.data[j];
    for (j = 1; j <= s2.data[0]; j++)     //新的串 从i开始 (共s2个)
        str.data[i + j - 1] = s2.data[j]; //(空位:s2+i是空的)
    for (j = i; j <= s1.data[0]; j++)     //后半段(原来的i不可以丢)
        str.data[s2.data[0] + j] = s1.data[j];
    str.data[0] = s1.data[0] + s2.data[0];
    return str;
}
skr del(skr s, int i, int j)
{ //《删除·i起删除j个》
    int k;
    skr str;
    str.data[0] = 0;
    if (i <= 0 || i > s.data[0] || i + j > s.data[0] + 1) //参数不正确时返回空串
        return str;
    for (k = 1; k <= i - 1; k++) // i-1前给str
        str.data[k] = s.data[k];
    for (k = i + j; k <= s.data[0]; k++) // i+j开始接上去
        str.data[k - j] = s.data[k];
    str.data[0] = s.data[0] - j;
    return str;
}
skr replace(skr s, int i, int j, skr t)
{ //《替换·s中i开始j个·换成t》
    int k, S1 = s.data[0], S2 = t.data[0];
    skr T;
    if (i <= 0 || i > S1 || i + j > S1 + 1) //参数不正确时返回空串  例如6个 从5起替换2个,换掉5和6,是可以的,但是5+2=7=6+1>6,这是可以的;但是再+1不行
        return T;
    for (k = 1; k <= i - 1; k++) // s的前i-1进去 (总长:i-1)(下个空点:i)
        T.data[k] = s.data[k];
    for (k = 1; k <= S2; k++) //替换区进去 (总长:i-1+s2)(下个空点:i+s2)
        T.data[i - 1 + k] = t.data[k];
    for (k = i + j; k <= S1; k++) //后段接入
        T.data[S2 + k - j] = s.data[k];
    T.data[0] = S1 - j + S2;
    return T;
}
void print(skr s)
{ //《输出·串》
    int i;
    if (s.data[0] > 0)
        for (i = 1; i <= s.data[0]; i++)
            printf("%c", s.data[i]);
}
void menu(skr s1, skr s2)
{ //《菜单》
    system("cls");
    printf("S1:   ");
    print(s1);
    printf("   长度:%d\n", len(s1));
    printf("S2:   ");
    print(s2);
    printf("   长度:%d\n", len(s2));
    printf("1-创建s1\t2-创建s2\t3-插入\t4-删除\n");
    printf("5-替换\t\r6-提取\t\t7-连接\t\t8-清空\t9-查找\n10-get_nextval\n");
    printf("请输入您的选择:");
}
bool clear(skr &s)
{ //《清空》
    s = del(s, 1, s.data[0]);
    s.data[0] = 0;
}
int search(skr s1, skr s2, int t)
{ //《查找·相同串》s1更长,s2是子串 复杂度O(n*m)
    int i = t, j = 1;
    printf("\n采用暴力算法!O(n*m)\n");
    // printf("%d %d %d %d\n",s1.data[0],s2.data[0],i,j);
    while (i <= s1.data[0] && j <= s2.data[0])
    { //主串读取完成·已经发现了子串·则跳出
        if (s1.data[i] == s2.data[j])
        {
            i++;
            j++;
            // printf("i=%d j=%d 相同!  j=%d\n",i-1,j-1,j);
        }
        else
        {
            // printf("i=%d j=%d 不同!",i,j);
            i = i - j + 2;
            j = 1;
            // printf("  i=%d,j=%d\n",i,j);
        }
        // printf("%d %d %d\n",i,s2.data[0],i-s2.data[0]);
    }
    if (j == s2.data[0] + 1)
        return i - s2.data[0];
    else
        return 0;
}
bool map(int x, int y, skr s2, int t[])
{ //《反馈·指针情况》
    printf("-----------------------------------------\n");
    printf("x=%d\ty=%d\n", x, y);
    int i;
    for (i = 1; i <= x; i++)
        printf(" ");
    printf("X\n ");
    print(s2);
    printf("\n");
    for (i = 1; i <= y; i++)
        printf(" ");
    printf("Y\n ");
    for (i = 1; i <= s2.data[0]; i++)
        printf("%d", t[i]);
    printf("\n");
    return true;
}
bool map2(int x, int y, skr s1, skr s2, int t[])
{ //《反馈·指针情况》
    printf("\n");
    int i; // 1主串  2子串
    for (i = 1; i <= x; i++)
        printf(" ");
    printf("X\n ");
    print(s1);
    printf("\n ");
    print(s2);
    printf("\n");
    for (i = 1; i <= y; i++)
        printf(" ");
    printf("Y\n ");
    for (i = 1; i <= s2.data[0]; i++)
        printf("%d", t[i]);
    printf("\n\n");
    return true;
}
void get_next(skr s2, int t[])
{ //《KMP辅助!由子串生成back数组》
    int x = 1, y = 0;
    t[1] = 0;
    while (x < s2.data[0])
    {
        // map(x, y, s2, t);
        if (y == 0 || s2.data[x] == s2.data[y])
        { /*
             if (s2.data[x] == s2.data[y])
                 printf("  相同");
             else
                 printf("  虚无");*/
            t[++x] = ++y;
            // printf("的元素!x、y各+1。t[%d]=%d\n", x, y);
        }
        else
        {
            // printf("  不同的元素!y由%d退回到%d\n", y, t[y]);
            y = t[y];
        } /*
         if (x == s2.data[0])
             printf("-----------------------------------------\n");*/
    }
}
int KMP(skr s1, skr s2, int t)
{ //《查找·相同串》s1更长,s2是子串 KMP算法 复杂度O(n+m)
    printf("\n启用KMP算法!·O(n+m)\n");
    int back[max] = {}, x, y, z, k = 0;
    get_next(s2, back);
    printf("NEXT情况报备:");
    for (x = 1; x <= s2.data[0]; x++)
        printf("%d ", back[x]);
    printf("\n");
    x = t;
    y = 1; //从t开始找,包括t       x在右边,是主串指针,y是子串指针
    while (x <= s1.data[0] && y <= s2.data[0])
    {
        // printf("%d:\t", ++k);
        // printf("x=%d  y=%d", x, y);
        // map2(x, y, s1, s2, back);
        if (y == 0 || s1.data[x] == s2.data[y])
        { /*
             if (s1.data[x] == s2.data[y])
                 printf("相同");
             else
                 printf("启封");*/
            x++;
            y++;
            // printf("的元素!x、y各+1  .\n");
        }
        else
        {
            // printf("不同的元素!将y从%d回溯到%d\n", y, back[y]);
            y = back[y];
        }
        // printf("--------------------------------------------------\n");
    }
    //如果追踪成功,那么y指针,实际数值 = 子串总长度+1
    if (y == s2.data[0] + 1)
    {
        //printf("x=%d  y=%d  y溢出!说明子串遍历完成。\n子串长度:%d。\n", x, y, s2.data[0]);
        return x - s2.data[0];
    }
    else
        return 0; //总长8,结束x=9,子串3,9-3=6,恰好=相同子串打头位置
} //优点在于不用回溯i指针,而是利用 部分匹配+滑动的机制

int main()
{
    skr s1, s2, s3, s4;
    s1.data[0] = 0;
    s2.data[0] = 0;
    s3.data[0] = 0;
    s4.data[0] = 0;
    int x, y, z, k[max];
    char a[max], t;
    while (1)
    {
        menu(s1, s2);
        scanf("%d", &x);
        printf("\n");
        switch (x)
        {
        case 1:
        { //《创建s1》
            printf("输入S1字符串:");
            scanf("%c", &t); //挡住回车键
            gets(a);
            create(s1, a);
            break;
        }
        case 2:
        { //《创建s2》
            printf("输入S2字符串:");
            scanf("%c", &t);
            gets(a);
            create(s2, a);
            break;
        }
        case 3:
        { //《插入》
            printf("谁被插入?互插 或 新建?插入位置?");
            scanf("%d%d%d", &x, &y, &z);
            if (x == 1 && y == 1)
                s1 = insert(s1, z, s2);
            if (x == 2 && y == 1)
                s2 = insert(s2, z, s1);
            if (y == 2)
            {
                printf("输入字符串s3:");
                scanf("%c", &t); //挡住回车键
                gets(a);
                create(s3, a);
                if (x == 1)
                    s1 = insert(s1, z, s3);
                if (x == 2)
                    s2 = insert(s2, z, s3);
            }
            break;
        }
        case 4:
        { //《删除·可选》
            printf("对z进行操作,第x起删除y个:");
            scanf("%d%d%d", &z, &x, &y);
            if (z == 1 && s1.data[0] != 0)
                s1 = del(s1, x, y);
            if (z == 2 && s2.data[0] != 0)
                s2 = del(s2, x, y);
            break;
        }
        case 5:
        { //《替换》
            printf("z被替换,替换的字符段x起共y个(包括x):");
            scanf("%d%d%d", &z, &x, &y);
            if (x == 1)
                s1 = replace(s1, x, y, s2);
            if (x == 2)
                s2 = replace(s2, x, y, s1);
            break;
        }
        case 6:
        { //《提取》
            printf("从哪个串开始提取?从x起共y个?");
            scanf("%d%d%d", &z, &x, &y);
            if (z == 1)
                s3 = take_out(s1, x, y);
            else if (z == 2)
                s3 = take_out(s2, x, y);
            else
                break;
            if (s3.data[0] == 0)
                break;
            printf("捕获子串!  ");
            print(s3);
            printf("\n");
            break;
        }
        case 7:
        { //《连接》
            printf("是s1后接s2?");
            scanf("%d", &x);
            if (x == 1)
                s3 = contact(s1, s2);
            if (x == 0)
                s3 = contact(s2, s1);
            printf("完成链接!  ");
            print(s3);
            printf("\n");
            break;
        }
        case 8:
        { //《清空》
            printf("清空谁:");
            scanf("%d", &x);
            if (x == 1)
                clear(s1);
            if (x == 2)
                clear(s2);
            break;
        }
        case 9:
        { //《查找·子串》
            printf("谁是主串?从第几个开始查找?是否采用KMP算法?");
            scanf("%d%d%d", &x, &y, &z);
            if (x == 1 && z == 0)
                z = search(s1, s2, y);
            else if (x == 2 && z == 0)
                z = search(s2, s1, y);
            else if (x == 1 && z == 1)
                z = KMP(s1, s2, y);
            else if (x == 2 && z == 1)
                z = KMP(s2, s1, y);
            if (z != 0)
                printf("发现子串!位于%d\n", z);
            break;
        }
        case 10:
        {                    //《get_nextval》
            scanf("%c", &t); //挡住回车键
            gets(a);
            create(s4, a);
            get_nextval(s4, k);
            break;
        }
        }
        printf("\n");
        system("pause");
    }
    return 0;
}

明明一个char a[233]就能搞定了,为什么书上非要搞个typedef?对我这种菜鸟很不友好

这个代码还能改进成非typedef的,但是由于我不会在函数中引用char数组,所以只好先这样

关于KMP的next数组生成的算法

将子串从头开始,拆2个,拆3个,拆4个,一直到拆n个,称为“拆解子串”

X:尾部指针,指向 拆解子串尾部

Y:头部指针,记录当前 最大公共前后缀的长度

next[x+1]:如果x+1位置不对,他要跳到哪个位置去?

T1如果(头部指针指向虚无/存在相同元素)

t[++x]=++y; 先都+1,再赋值

1.指向虚无不存在相同的元素,那么结论出来了

x+1位置不对,从头(1)开始找吧

2.存在相同,说明x+1不同时,跳到 Y+1

(即可保证,前边Y个元素  和  异动前的Y个元素  相同)

对于x长度子串的分析,意义是对于x+1的位置

如果x+1位置不对,他要跳到哪个位置去?

答案:当前最长公共前后缀长度+1 叫做 Y+1

所以next[x+1]=y+1(翻译:x+1位置不对,跳到Y+1)

T2否则,对y进行回溯

Y移到 t[y]

前段的t[y]-1个元素和移动前是相同的

而赋值后的y,也就是之前的t[y]

头部指针,当前点,需要再次验证,是否和尾部相同

如果是(第二轮if),说明 当前的Y就是 当前的最大公共子序列长度

(Y指向5,那么 包括Y以及前面的点 都和 包括尾指针X起5个点  相同)

如果不是(第二轮else)说明现在Y点以及之前的点不对,还要继续回溯

利用next[x]回溯,目的是:让前面部分尽可能保持一致前提下

加快回跳速度,绕开一些不必要的比对

而不是一步一步往回退

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

影月丶暮风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值