02字符串的暴力匹配和kmp算法(C语言版)

1字符串暴力匹配

具体原理不过多解释。
代码如下:

#include<stdio.h>
#include<stdlib.h>


typedef struct String{
    char* data;//C里面没有字符串的概念,所以需要字符型指针来代替这个而且最后一个是\0结尾.
    int len;
}String;

//初始化
String* initString(){
    String* S=(String*)malloc(sizeof(String));
    S->data=NULL;
    S->len=0;
    return S;
}
//data的数据需要一个输入函数,因此需要写一个输入函数
void stringAssign(String*s,char* data){
    if(s->data){
        free(s->data);
    }
    int len=0;//字符串有多长
    char * temp=data;//找一个变量代替data
    while(*temp){//data
        len++;
        temp++;//数组的第一个元素,顺序表的直接加一,不需要考虑指针
    }
    s->len=len;
    //上面得到data的长度len,temp指向最后一个data[len-1];
    if(len == 0){//为空
        s->data=NULL;
        //s->len=0;
    }
    else{
        //有值
       // s->len=len;
       temp=data;
       //开辟空间的理解还是不够
       s->data=(char*)malloc(sizeof(char)*(len+1));//多一个存\0
       //为什么要开辟空间呢?因为我要输入一个值,那么我希望得到一些内存空间。
       for(int i=0;i<len;i++,temp++){
        s->data[i]=*temp;//学习这种表示方式,*temp=data[i];
       }
    } 
}



//输出字符串
void printString(String* s){
    for(int i=0;i< (s->len);i++){
        printf(i==0 ? "%c":"->%c",s->data[i]);//注意i==0!!
       }
    printf("\n");
}

//完成暴力匹配算法
void forceMatch(String* master,String* sub){
    //定义两个指针
    int i=0;
    int j=0;//这样跟int i,j=0;有区别吗???
    //int a,b=0;//a为随机值
    //printf("a=%d,b=%d\n",a,b); tmd,没想到在这里翻车了
    while(i<master->len && j < sub->len){//master,sub同时越过字符串
        if(master->data[i] == sub->data[j]){
           i++;//匹配
           j++;
        }
        else{//不匹配的时候要回溯
          i=i-j+1;
          j=0;
        }
    }
    printf("master->len=%d\n",master->len);
    printf("sub->len=%d\n",sub->len);
    printf("j=%d\n",j);//为什么j=1??
    //循环完毕,进行判断
    if(j == sub->len ){
        printf("匹配成功.\n");
    }
    else{
        printf("不匹配.\n");
    }

}
int main(){
    String* s=initString();
    stringAssign(s,"heoh");
    printString(s); 
    String* s1=initString();
    stringAssign(s1,"he");
    printString(s1); 
    forceMatch(s,s1);
    return 0;
}

02kmp算法

2.1定义

更详细的算法解释:kmp算法描述
(1)next 数组的求解:就是找最大对称长度的前缀后缀,然后整体右移一位,初值赋为-1。
在这里插入图片描述
(2)而最大对称长度的前缀后缀怎么求呢?
在这里插入图片描述
上图为推导过程,具体的代码实现如下:

#include<stdio.h>
#include<stdlib.h>

#define MAXSIZE 5

typedef struct String{
    char* data;//C里面没有字符串的概念,所以需要字符型指针来代替这个而且最后一个是\0结尾.
    int len;
}String;

//初始化
String* initString(){
    String* S=(String*)malloc(sizeof(String));
    S->data=NULL;
    S->len=0;
    return S;
}
//data的数据需要一个输入函数,因此需要写一个输入函数
void stringAssign(String*s,char* data){
    if(s->data){
        free(s->data);
    }
    int len=0;//字符串有多长
    char * temp=data;//找一个变量代替data
    while(*temp){//data
        len++;
        temp++;//数组的第一个元素,顺序表的直接加一,不需要考虑指针
    }
    s->len=len;
    //上面得到data的长度len,temp指向最后一个data[len-1];
    if(len == 0){//为空
        s->data=NULL;
        //s->len=0;
    }
    else{
        //有值
       // s->len=len;
       temp=data;
       //开辟空间的理解还是不够
       s->data=(char*)malloc(sizeof(char)*(len+1));//多一个存\0
       //为什么要开辟空间呢?因为我要输入一个值,那么我希望得到一些内存空间。
       for(int i=0;i<len;i++,temp++){
        s->data[i]=*temp;//学习这种表示方式,*temp=data[i];
       }
    } 
}



//输出字符串
void printString(String* s){
    for(int i=0;i< (s->len);i++){
        printf(i==0 ? "%c":"->%c",s->data[i]);//注意i==0!!
       }
    printf("\n");
}

//完成暴力匹配算法
void forceMatch(String* master,String* sub){
    //定义两个指针
    int i=0;
    int j=0;//这样跟int i,j=0;有区别吗???
    //int a,b=0;//a为随机值
    //printf("a=%d,b=%d\n",a,b); tmd,没想到在这里翻车了
    while(i<master->len && j < sub->len){//master,sub同时越过字符串
        if(master->data[i] == sub->data[j]){
           i++;//匹配
           j++;
        }
        else{//不匹配的时候要回溯
          i=i-j+1;
          j=0;
        }
    }
    printf("master->len=%d\n",master->len);
    printf("sub->len=%d\n",sub->len);
    printf("j=%d\n",j);//为什么j=1??
    //循环完毕,进行判断
    if(j == sub->len ){
        printf("匹配成功.\n");
    }
    else{
        printf("不匹配.\n");
    }
}
//kmp算法:
int* getNext(String* s){
    int* next =(int*)malloc(sizeof(int)*s->len);
    int i=0;
    int j=-1;
    next[i]=-1;
    while(i < s->len-1){
        if(j == -1 || s->data[i] == s->data[j]){
            i++;
            j++;
            next[i]=j;
        }
        else{
            j=next[j];
        }
    }return next;    
}
//kmp算法
void kmpMatch(String* master, String* sub, int* next) {
    int i = 0;
    int j = 0;
    while (i < master->len && j < sub->len) {
        if (j == -1 || master->data[i] == sub->data[j]) {
            i++;
            j++;
        } else {
            j = next[j];
        }
    }
    if (j == sub->len) {
        printf("kmp match success.\n");
    } else {
        printf("kmp match fail.\n");
    }
}
//打印next
void printnext(int * next,int len){
    for(int i=0;i<len;i++){
        printf(i == 0 ? "%d":"->%d",next[i]+1);
    }
    printf("\n");
}
int main(){
    String* s=initString();
    stringAssign(s,"heosfhakfhfah");
    printString(s); 
    String* s1=initString();
    stringAssign(s1,"heos");
    printString(s1); 

    int *next=getNext(s1);
    printnext(next,s1->len);
    forceMatch(s,s1);
    kmpMatch(s,s1,next);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值