数据结构:KMP算法

KMP算法是BF算法的改良版。

BF算法链接

#include<stdio.h>

#define MAXSIZE 30


typedef struct {
    char ch[MAXSIZE + 1];
    int length;
} sstring;

//新建串
void setdata(sstring *w, char data) {
    w->ch[w->length] = data;
}

//显示串内元素
void appear(sstring S) {
    printf("\n串内元素为:");
    for (int i = 0; i < S.length; i++)
        printf("%c", S.ch[i + 1]);
    printf("\n串内元素有%d个\n\n", S.length);
}

//普通版
void geti(sstring T, int ival[]) {
    ival[1] = 0;
    ival[2] = 1;
    for (int ww = 3; ww <= T.length; ww++) {

        if (T.ch[ival[ww - 1]] == T.ch[ww - 1])        //比较往后新增一个字符,两个部分是否还相等
            ival[ww] = ival[ww - 1] + 1;                //相等的话,这里的值就比前一个加一
        else                                    //不等的话
        if (T.ch[1] == T.ch[ww - 1])                //就从头开始比较,要么为2,要么为1
            ival[ww] = 2;
        else
            ival[ww] = 1;
    }
}

//修正版
//这里没有使用上面计算出的i值,而是独立成块
void getipro(sstring T, int ival[]) {
    ival[1] = 0;

    if(T.ch[ival[1]]==T.ch[ival[2]])          //第二个数非0即1
        ival[2] = 0;
    else
        ival[2] = 1;

    ival[0] = 1;            //合理运用第一个空位,存放每个位置上的普通版的i值
    //开始判断后面所有的数
    for (int ww = 3; ww <= T.length; ww++) {
       //承接前面已匹配到的位置,继续往后匹配
        if (T.ch[ival[0]] == T.ch[ww - 1]) {
            //继承成功的话,就继续判断下一个字符是否相等
            if (T.ch[ival[0] + 1] == T.ch[ww])
                //相等的话就左右取
                ival[ww] = ival[ival[0] + 1];
            else
                //不等的话就上下取
                ival[ww] = ival[0] + 1;
            //只要继承成功,i值就会往下增
            ival[0]++;
        }
        //当继承不了前面的值的时候,就从第一个重新开始
        else if (T.ch[1] == T.ch[ww - 1]) {
            printf("进入了这里");
            //只要进入这里,就说明有一个字符相等了,所以说取值为2
            ival[0] = 2;
            if (T.ch[2] == T.ch[ww])
                //相等的话就左右取
                ival[ww] = ival[2];
            else
                ival[ww] = ival[2]+1;
        }
        //
        else {
            ival[0] = 1;
            if (T.ch[1] == T.ch[ww])
                ival[ww] = 0;
            else
                ival[ww] = 1;
        }
    }
}

int bmw(sstring S, sstring L, int i, int j) {
    while (S.ch[i] == L.ch[j]) {
        if (i <= S.length && j == L.length)
            return 999;
        if (i == S.length && j < L.length)
            return 0;
        i++;
        j++;
    }
    return j;
}


int KMP(sstring S, sstring L, int location, int iii[]) {
    int i = location, w = 1;
    while (i <= S.length && w <= L.length) {
        int ss = bmw(S, L, i, w);
        if (ss == 999)
            return i;
        i++;
        w = iii[ss]+1;
    }
    return 0;
}


void main() {

    char data;

    int location;
    printf("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");
    sstring S;
    sstring L;
    S.length = L.length = 0;
    printf("请输入主串内的元素(以#结尾):\n");
    scanf("%c", &data);
    while (data != '#') {
        S.length++;
        setdata(&S, data);
        scanf("%c", &data);
    }
    appear(S);

    printf("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n");
    printf("请输入副串内的元素(以#结束):\n");
    fflush(stdin);
    scanf("%c", &data);
    while (data != '#') {
        L.length++;
        setdata(&L, data);
        scanf("%c", &data);
    }
    appear(L);
    printf("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n");
    printf("请输入您想开始比较的位置\n");
    scanf("%d", &location);
    printf("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n\n");

    int iiii[MAXSIZE + 1], iii[MAXSIZE + 1];                //第一个位置空出来
    geti(L, iiii);
    getipro(L, iii);

    int www = KMP(S, L, location, iii);
    if (www)
        printf("主串内含有副串,位置为:%d\n", www);
    else
        printf("主串内无副串。\n");


    for (int ss = 1; ss <= L.length; ss++)
        printf("%d\t", iiii[ss]);
    printf("\n");

    for (int sss = 1; sss <= L.length; sss++)
        printf("%d\t", iii[sss]);

}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值