吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1071|回复: 0
收起左侧

[C&C++ 转载] C语言 在链式结构体的字符串中使用KMP算法

[复制链接]
ForestFairy 发表于 2020-10-30 17:19
[C] 纯文本查看 复制代码
/*字符串*/

#include <stdio.h>

#include <stdlib.h>

#include <malloc.h>



typedef char DataType;

typedef struct Char

{

    DataType data;

    struct Char *prior, *next;

}Char;

typedef struct Str

{

    struct Char *C;

}Str;



void StrInit(Str *S);

void StrCreate(Str *S, char* CH, int len);

Str StrAssign(Str *S, Str *T);

int StrLength(Str *S);

Str StrCat (Str *S, Str *T);

Str StrSub (Str *S, int i, int len);

int StrCmp (Str *S, Str *T);

Str *GetNext(Str *T);

int StrIndex(Str *S, Str *T);

Str StrInsert(Str *S, Str *T, int i);

Str StrDelete (Str *S, int i, int len);

int StrPrint(Str *S);



int main()

{

    Str S, T;

    char A[] = "ababccca", B[] = "abc";

    int i, lenA, lenB;

    lenA = sizeof(A)-1;

    lenB = sizeof(B)-1;

    StrInit(&S);

    StrInit(&T);

    StrCreate(&S, A, lenA);

    if(StrPrint(&S))

        printf("打印完毕!\n");

    else

        printf("字符串为空!\n");

    printf("Length of S: %d\n",StrLength(&S));

    printf("Length of T: %d\n",StrLength(&T));

    StrCreate(&T, B, lenB);

    S = StrAssign(&S, &T);

    if(StrPrint(&S))

        printf("打印完毕!\n");

    else

        printf("字符串为空!\n");

    printf("Length of S: %d\n",StrLength(&S));

    printf("Length of T: %d\n",StrLength(&T));

    StrCreate(&S, A, lenA);

    if(StrPrint(&S))

        printf("打印完毕!\n");

    else

        printf("字符串为空!\n");

    printf("Length of S: %d\n",StrLength(&S));

    printf("Length of T: %d\n",StrLength(&T));

    S = StrCat(&S,&T);

    if(StrPrint(&S))

        printf("打印完毕!\n");

    else

        printf("字符串为空!\n");

    printf("Length of S: %d\n",StrLength(&S));

    printf("Length of T: %d\n",StrLength(&T));

    T = StrSub(&S, 2, 11);

    printf("从主串S第二个字符开始截取到结束后的子串T:\n");

    if(StrPrint(&T))

        printf("打印完毕!\n");

    else

        printf("字符串为空!\n");

    printf("Length of S: %d\n",StrLength(&S));

    printf("Length of T: %d\n",StrLength(&T));

    printf("主串S与子串T比较:\n");

    if(StrCmp(&S, &T) == -1)

        printf("S < T ! \n");

    else if(StrCmp(&S, &T))

        printf("S > T ! \n");

    else

        printf("S = T ! \n");

    T = StrSub(&S, 9, 3);

    printf("截取主串S后三个字符后的子串T\n");

    if(StrPrint(&T))

        printf("打印完毕!\n");

    else

        printf("字符串为空!\n");

    if(i = StrIndex(&S, &T))

        printf("子串T在主串S中首次出现的位置为: %d\n", i+1);

    else

        printf("主串S中无子串T\n");

    S = StrInsert(&S, &T, i);

    printf("主串S在第 3 个位置插入子串T后的数据为:\n");

    if(StrPrint(&S))

        printf("打印完毕!\n");

    else

        printf("字符串为空!\n");

    S = StrDelete(&S, 8, 3);

    printf("主串S第 8 个位置往后删除 3 个数据后为:\n");

    if(StrPrint(&S))

        printf("打印完毕!\n");

    else

        printf("字符串为空!\n");

    return 0;

}



void StrInit(Str *S)        //字符串头初始化

{

    Char *SC = (Char *)malloc(sizeof(Char));

    SC->next = SC->prior = NULL;

    S->C = SC;

}



void StrCreate(Str *S, char* CH, int len) //生成字符串

{

    if(len == 0)

    {

        printf("error! the length is 0!");

        return;

    }

    int count = 0;

    Char *p = NULL, *q = NULL;

    p = S->C->next;

    while(p != NULL)

    {

        q = p;

        p = p->next;

        free(q);

    }

    p = S->C;

    while(count < len)

    {

        Char *s = (Char *)malloc(sizeof(Char));

        s->data = CH[count++];

        p->next = s;

        s->next = NULL;

        s->prior = p;

        p = p->next;

    }



}



Str StrAssign(Str *S, Str *T) // make S to T.

{

    Char *p, *p2, *q;

    p = S->C;

    p2 = p->next;

    q = T->C->next;

    while(q != NULL)

    {

        Char *s = (Char *)malloc(sizeof(Char));

        s->data = q->data;

        s->next = NULL;

        s->prior = p;

        p->next = s;

        p = p->next;

        q = q->next;

    }

    while(p2 != NULL)

    {

        p = p2;

        p2 = p2->next;

        free(p);

    }

    return *S;

}



int StrLength(Str *S) //get length of String.

{

    int i = 0;

    Char *p = NULL;

    p = S->C;     //point at the first data area.

    while(p->next != NULL)

    {

        p = p->next;

        i++;

    }

    return i;

}



Str StrCat (Str *S, Str *T)  //catch T to S;

{

    Char *p = NULL, *q = NULL;

    p = S->C;

    q = T->C;

    while(p->next != NULL)

        p = p->next;

    p->next = q->next;

    if(q->next != NULL)

        q->next->prior = p;

    return *S;

}



Str StrSub (Str *S, int i, int len)

{

    int count = 0;

    Str ST, *T;

    StrInit(&ST);

    Char *p = NULL, *q = NULL;

    T = &ST;

    p = S->C;

    q = T->C;

    while(count < i && p->next != NULL)

    {

        count++;

        p = p->next;

    }

    count = 0;

    while(count < len && p != NULL)

    {

        count++;

        Char *s = (Char *)malloc(sizeof(Char));

        s->data = p->data;

        s->next = NULL;

        s->prior = q;

        q->next = s;

        q = q->next;

        p = p->next;

    }

    return ST;

}



int StrCmp (Str *S, Str *T)

{

    Char *p = NULL, *q = NULL;

    p = S->C->next;

    q = T->C->next;

    while(p != NULL && q != NULL)

    {

        if(p->data > q->data) return 1;

        else if (p->data < q->data) return -1;

        p = p->next;

        q = q->next;

    }

    if(p != NULL && q == NULL) return 1;

    else if(p == NULL && q != NULL) return -1;

    return 0;

}



Str *GetNext(Str *T) //方法①:将T赋值给字符数组 其余代码照原 方法② 找到取代利用next[]记录位置的方法

{

    Str *Next, Next1;  //记录: 将匹配到的结点 的下一结点 通过next连接起来, 再取的该结点,即存储结点的前驱。

    StrInit(&Next1);//结点数为T的结点数-1

    Next = &Next1;

    Char *p, *q, *kp, *kq;

    p = T->C;

    q = p->next;

    kp = Next->C;

    kp->prior = T->C;

    while(q != NULL)

    {

        if(p == T->C || p->data == q->data)

        {

            p = p->next;

            q = q->next;

            Char *s = (Char *)malloc(sizeof(Char));

            s->prior = p;

            s->next = NULL;

            kp->next = s;

            kp = kp->next;

        }

        else

        {

            if(p->prior != NULL)

                p = p->prior;

        }

    }

    return Next;

}



int StrIndex(Str *S, Str *T)    //基于KMP算法的子串查找

{

    if(StrLength(S)<StrLength(T))

    {

        printf("主串长度小于子串长度!");

        return 0;

    }

    Str *Next;

    Next = GetNext(T);

    Char *p, *q, *Np, *Nq, *lastp1, *lastp2; //lastp1 p2,p1 用于记录最后一次不同的主串结点, p2 用于记录最后一次因不同而跳语句跳到相同的结点。

    int count = 1, i = 0, k = 0, op = 0;;

    p = S->C;

    q = T->C;

    lastp1 = p;

    lastp2 = p->next;

    Np = Next->C;

    Nq = Next->C;

    while(q != NULL)

    {

        if(q == T->C || p->data == q->data)

        {

            p = p->next;

            q = q->next;

            if(i++)

            {

                Nq = Np;

                if(Np->next != NULL)

                    Np = Np->next;

            }

            k++;

        }

        else

        {

            q = Np->prior;

            if(Np != Nq)

                Np = Nq;

            lastp1 = p;

            if(q == T->C->next && p->data != q->data)

            {

                Np = Nq = Next->C;

                q = T->C;

                i = 0;

            }

            if(p->data == q->data)

                lastp2 = p;

            count = k;

        }

        if(p == NULL && q != NULL)

            return 0;

    }

    if(lastp1 == lastp2)

        count--;

    return count;

}



Str StrInsert(Str *S, Str *T, int i)

{

    if(StrLength(S) < i)

    {

        printf("下溢错误!\n");

        return *S;

    }

    Char *ps, *qs, *pt, *qt;

    int count = 0;

    ps = S->C;

    pt = T->C->next;

    while(count < i && ps != NULL)

    {

        count++;

        ps = ps->next;

    }

    qs = ps->next;



    while(pt != NULL)

    {

        Char *s = (Char *)malloc(sizeof(Char));

        s->data = pt->data;

        s->next = NULL;

        s->prior = ps;

        ps->next = s;

        ps = ps->next;

        pt = pt->next;

    }

    ps->next = qs;

    if(qs != NULL)

        qs->prior = ps;

    return *S;

}



Str StrDelete (Str *S, int i, int len)

{

    if(StrLength(S)<i)

    {

        printf("下溢错误! \n");

        return *S;

    }

    Char *p, *q;

    int count = 0;

    p = S->C;

    while(count < i && p != NULL)

    {

        p = p->next;

        count++;

    }

    q = p;

    count = 1;

    while(count < len && p != NULL)

    {

        p = p->next;

        count++;

    }

    if(p->next != NULL)

        p->next->prior = q->prior;

    q->prior->next = p->next;

    q->prior = NULL;

    p->next = NULL;

    while(q != NULL)

    {

        p = q;

        q = q->next;

        free(p);

    }

    return *S;

}



int StrPrint(Str *S)

{

    Char *p;

    p = S->C->next;

    if(p == NULL)

        return 0;

    while(p != NULL)

    {

        printf(" %c \n",p->data);

        p = p->next;

    }

    return 1;

}


看到没多少关于KMP算法相关的帖子,相关的也只是直接字符数组。但是在我C语言数据结构的课本里似乎要求的是要将字符存进链式结构体的字符串。然后就自己学习套用下该算法,用于我自己敲的这个字符串里面,目前还没发现什么毛病。   其实今天已经在其他的论坛发过了,不过没什么阅读量,没大佬指出问题。发这希望有大佬帮我看看

免费评分

参与人数 3吾爱币 +11 热心值 +3 收起 理由
苏紫方璇 + 10 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
明明如月52 + 1 + 1 楼主辛苦
天上飞来一只 + 1 热心回复!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 23:35

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表