道化師 发表于 2024-5-13 20:12:26

KMP算法的实现

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

//给char * 起名为String
typedef char* String;

//定义一个结构体,str存储字符串,cap存储字符串的长度
typedef struct
{
      char str;
      int cap;
}Str;

//获取next数组,这个是KMP算法的灵魂
void get_next(Str *T, int *next )
{
      int j = 0;
      int i = 1;
      next = 0;
      
      while( i < T->str )   //当循环次数超过字符串的长度的时候退出循环
      {
                if( 0 == j || T->str == T->str )
                {
                        i++;
                        j++;
                        if( T->str != T->str )    //改进后的算法
                        {
                              next = j;
                        }
                        else
                        {
                              next = next;
                        }
                }
                else
                {
                        j = next;
                }
      }
}

// 返回子串T在主串S第pos个字符之后的位置
// 若不存在,则返回0
int Index_KMP( Str *S, Str *T, int pos )
{
      int i = pos;
      int j = 1;
      int next;
      
      get_next( T, next );
      
      while( i <= S->cap && j <= T->cap)
      {
      //增加判断,防止特殊情况发生
                if( 0 == j || S->str == T->str )
                {
                        i++;
                        j++;
                }
                else
                {
                        j = next;
                }
      }
      
      if( j > T->cap )
      {
                return i - T->cap;
      }
      else
      {
                return 0;
      }
}

//创建存储容量和字符串的结构,这里需要改变结构体的内容,所以传入指向指针的指针
void CreateStr(Str **S)
{
      *S = (Str *)malloc(sizeof (Str));
      if (!S)
      {
                perror("INIT:malloc");
                exit(EXIT_FAILURE);
      }
      
      printf("请输入一个字符串,输入回车结束:");
      char ch;
      int i = 0;
      
      while ((ch = getchar()) != '\n')
      {
                (*S)->str = ch;   //后置++,先赋值,后++
      }
      //这里i相当与字符串的长度
      (*S)->cap = i;
      
}

int main(void)
{
      Str *S = NULL;
      Str *T = NULL;
      int pos = 1;
      int status = 0;
      
      CreateStr(&S);
      CreateStr(&T);
      
      status = Index_KMP(S, T, pos);
      
      if (1 == status)
      {
                printf("是");
      }
      else
      {
                printf("否");      
      }
      

FishC 发表于 2024-5-13 20:13:07

这段代码实现了KMP算法,用来查找子串在主串中的位置。不过代码中有一些错误和不完善的地方,我来帮你解决。

首先,在函数get_next()中,你需要将next定义为数组,而不是整数。next数组存储的是匹配失败时下一次比较的位置,所以它的长度应该与字符串T的长度相同。修改代码如下:

void get_next(Str *T, int *next )
{
      int j = 0;
      int i = 1;
      next = 0; // 初始化next为0
      
      while( i < T->cap )   //修改为cap
      {
                if( 0 == j || T->str == T->str ) // 修改为str和str
                {
                        i++;
                        j++;
                        if( T->str != T->str )    //改进后的算法
                        {
                              next = j;
                        }
                        else
                        {
                              next = next;
                        }
                }
                else
                {
                        j = next;
                }
      }
}

接下来,在函数Index_KMP()中,你需要对pos的取值进行判断,保证在合法范围内。修改代码如下:

int Index_KMP( Str *S, Str *T, int pos )
{
      if (pos < 1 || pos > S->cap) {
                return 0; // pos超出范围,直接返回0
      }
      
      int i = pos;
      int j = 1;
      int next;
      
      get_next( T, next );
      
      while( i <= S->cap && j <= T->cap)// 小于等于号
      {
                if( j == 0 || S->str == T->str ) // 修改为str和str
                {
                        i++;
                        j++;
                }
                else
                {
                        j = next;
                }
      }
      
      if( j > T->cap )
      {
                return i - T->cap;
      }
      else
      {
                return 0;
      }
}

最后,在函数CreateStr()中,你没有为字符数组分配内存空间。修改代码如下:

void CreateStr(Str **S)
{
      *S = (Str *)malloc(sizeof (Str));
      if (!(*S))
      {
                perror("INIT:malloc");
                exit(EXIT_FAILURE);
      }

      printf("请输入一个字符串,输入回车结束:");

      int size = 10; // 假定初始容量为10
      int length = 0; // 用于记录字符串的长度
      char ch;

      (*S)->str = (char *)malloc(sizeof(char) * size); // 分配初始内存空间

      if (!((*S)->str))
      {
                perror("INIT:malloc");
                exit(EXIT_FAILURE);
      }

      while ((ch = getchar()) != '\n')
      {
                (*S)->str = ch;
                length++;

                if (length == size) // 当存储空间不够时,动态扩展内存
                {
                        size *= 2;
                        (*S)->str = (char *)realloc((*S)->str, sizeof(char) * size);
                        
                        if (!((*S)->str))
                        {
                              perror("INIT:realloc");
                              exit(EXIT_FAILURE);
                        }
                }
      }

      (*S)->cap = length; // 字符串的长度就是数组的大小
}

现在,你可以重新运行程序测试KMP算法了。记得在程序结束前,释放动态分配的内存空间,避免内存泄漏。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

ZZxxccvvbbnnmm 发表于 2024-5-14 01:25:00

ZZxxccvvbbnnmm 发表于 2024-5-14 01:25:51

QQQAAAXXX 发表于 2024-5-14 01:26:03

QQQAAAXXX 发表于 2024-5-14 01:26:43

LLkkjjhhggffdds 发表于 2024-5-14 01:26:56

LLkkjjhhggffdds 发表于 2024-5-14 01:27:31

LLkkjjhhggffdds 发表于 2024-5-14 01:28:10

AAssddffgghhjjk 发表于 2024-5-14 01:28:26

Mnklpo 发表于 2024-5-14 01:28:40

Mnklpo 发表于 2024-5-14 01:29:17

Mnklpo 发表于 2024-5-14 01:29:46

Poklmn 发表于 2024-5-14 01:30:03

MMnnbbvvccxxzz 发表于 2024-5-14 01:30:20

PPooiiuuyyttrre 发表于 2024-5-14 01:30:39

PPooiiuuyyttrre 发表于 2024-5-14 01:31:15

PPooiiuuyyttrre 发表于 2024-5-14 01:32:02

kerln888 发表于 2024-5-14 07:56:27

学习了

芜湖666 发表于 2024-5-14 16:20:08

sdf
页: [1] 2
查看完整版本: KMP算法的实现