【数据结构】字符串查找

实验7、字符串查找

目的

掌握字符串模式匹配的经典算法。

问题描述

分别用简单方法和KMP方法实现index在文本串中查找指定字符串的功能。

步骤

1.       定义字符串类型

2.       实现简单的index操作,从文本串中查找指定字符串。

3.       实现KMP方法的index操作,从文本串中查找指定字符串。

4.       []建立一个文本文件,读入每一行来测试自己完成的练习,观察并理解程序的各个处理。

设备和环境

PC计算机、Windows操作系统、C/C++开发环境

结论

能够理解和掌握字符串模式匹配的典型算法。

思考题

1.       KMP算法分别用手工和程序对某个模式串输出nextnextval




朴素算法:

#include<stdio.h>

#include<string.h>

 

#define NOTFOUND -1

#define ERROR -2

#define MAXLEN 100  //字符串的最大长度

 

char S[MAXLEN+10],T[MAXLEN+10],st[MAXLEN+10];   //S和串T

int S0,T0;                                      //S0:串S的长度 T0:串T的长度

int pos;                                        //pos的起始位置

 

void Init(char *S,int &S0)//读入字符串

{

    int len,i;

 

    New_Input:

    scanf("%s",st); //读入字符串

    len=strlen(st);

    if (len>MAXLEN) //如果字符串的长度大于规定的字符串最大长度

    {

        printf("This String is too long,Please Input a new one.nn");

        goto New_Input; //重新读入字符串

    }

 

    for (i=1;i<=len;i++) S[i]=st[i-1];

    S[len+1]='';

    S0=len;

}

 

int Index(char *S,char *T,int pos)

{

    if (pos<1 || pos>S0) return ERROR;  //  输入数据不合法

 

    int i=pos,j=1;

    while (i<=S0 && j<=T0)

    {

        if (S[i]==T[j]) {i++; j++;}

        else {i=i-j+2; j=1;}    //不匹配时,对应S移到下一位进行匹配

    }

    if (j>T0) return i-T0;  //返回S中找到的位置

    else return NOTFOUND;

}

 

int main()

{

    int ret;//函数返回值

 

    Init(S,S0);

    Init(T,T0);

 

    scanf("%d",&pos);

 

    ret=Index(S,T,pos); //S串中从pos这个位置起,找到第一个与T匹配的子串的起始位置

    if (ret==NOTFOUND) printf("Not Found.n");

    else if (ret==ERROR) printf("The Input Data is Error.n");

    else printf("In S,from %dth is equal to T.n",ret);

 

    return 0;

}


KMP:

 

 

#include<stdio.h>

#include<string.h>

 

#define NOTFOUND -1

#define ERROR -2

#define MAXLEN 100  //字符串的最大长度

 

char S[MAXLEN+10],T[MAXLEN+10],st[MAXLEN+10];   //S和串T

int S0,T0;                                      //S0:串S的长度 T0:串T的长度

int pos;                                        //pos的起始位置

 

int next[MAXLEN+10];

 

void Init(char *S,int &S0)//读入字符串

{

    int len,i;

 

    New_Input:

    scanf("%s",st); //读入字符串

    len=strlen(st);

    if (len>MAXLEN) //如果字符串的长度大于规定的字符串最大长度

    {

        printf("This String is too long,Please Input a new one.nn");

        goto New_Input; //重新读入字符串

    }

 

    for (i=1;i<=len;i++) S[i]=st[i-1];

    S[len+1]='';

    S0=len;

}

 

void Get_next(char *S,int *next)

{

    int i=1,j=0;

    next[1]=0;

    while (i<T0)

        if (j==0 || T[i]==T[j]) {i++; j++; next[i]=next[j];}

        else j=next[j];

}

 

int Index_KMP(char *S,char *T,int pos)

{

    int i=pos,j=1;

    while (i<=S0 && j<=T0)

        if (j==0 || S[i]==T[j]) {i++; j++;}

        else j=next[j];

    if (j>T0) return i-T0;

    else return NOTFOUND;

}

 

int main()

{

    int ret;//函数返回值

 

    Init(S,S0);

    Init(T,T0);

 

    scanf("%d",&pos);

 

    Get_next(T,next);

    ret=Index_KMP(S,T,pos); //S串中从pos这个位置起,找到第一个与T匹配的子串的起始位置

 

    if (ret==NOTFOUND) printf("Not Found.n");

    else if (ret==ERROR) printf("The Input Data is Error.n");

    else printf("In S,from %dth is equal to T.n",ret);

 

    return 0;

}

 

扩张KMP:

 

 

#include<stdio.h>

#include<string.h>

 

#define NOTFOUND -1

#define ERROR -2

#define MAXLEN 100  //字符串的最大长度

 

char S[MAXLEN+10],T[MAXLEN+10],st[MAXLEN+10];   //S和串T

int S0,T0;                                      //S0:串S的长度 T0:串T的长度

int pos;                                        //pos的起始位置

 

int nextval[MAXLEN+10];

 

void Init(char *S,int &S0)//读入字符串

{

    int len,i;

 

    New_Input:

    scanf("%s",st); //读入字符串

    len=strlen(st);

    if (len>MAXLEN) //如果字符串的长度大于规定的字符串最大长度

    {

        printf("This String is too long,Please Input a new one.nn");

        goto New_Input; //重新读入字符串

    }

 

    for (i=1;i<=len;i++) S[i]=st[i-1];

    S[len+1]='';

    S0=len;

}

 

void Get_nextval(char *S,int *nextval)

{

    int i=1,j=0;

    nextval[1]=0;

    while (i<T0)

        if (j==0 || T[i]==T[j])

        {

            i++; j++;

            if (T[i]!=T[j]) nextval[i]=j;

            else nextval[i]=nextval[j];

        }

        else j=nextval[j];

}

 

int Index_KMP(char *S,char *T,int pos)

{

    int i=pos,j=1;

    while (i<=S0 && j<=T0)

        if (j==0 || S[i]==T[j]) {i++; j++;}

        else j=nextval[j];

    if (j>T0) return i-T0;

    else return NOTFOUND;

}

 

int main()

{

    int ret;//函数返回值

 

    Init(S,S0);

    Init(T,T0);

 

    scanf("%d",&pos);

 

    Get_nextval(T,nextval);

    ret=Index_KMP(S,T,pos); //S串中从pos这个位置起,找到第一个与T匹配的子串的起始位置

 

    if (ret==NOTFOUND) printf("Not Found.n");

    else if (ret==ERROR) printf("The Input Data is Error.n");

    else printf("In S,from %dth is equal to T.n",ret);

 

    return 0;

}

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在C语言中,字符串是由字符组成的数组。字符串在C语言中以null字符('\0')作为结束标志。C语言中没有内置的字符串类型,但可以使用字符数组来表示字符串。使用字符数组可以进行字符串的操作和处理,比如拷贝、连接、比较等。 在数据结构中,字符串可以使用顺序存储结构(即字符数组)或链式存储结构(即链表)来实现。顺序存储结构是将字符串的字符顺序地存储在一维数组中,通过下标来访问和修改字符串的各个字符。链式存储结构是通过链表的方式将每个字符存储在节点中,并通过指针连接各个字符节点。 在字符串的操作中,常用的操作有字符串的复制、拼接、比较、查找子串等。在C语言中,可以使用标准库函数如strcpy、strcat、strcmp、strstr等来实现这些操作。另外,C++中的std::string类也是对字符串操作的封装,可以更方便地进行字符串处理。 总之,对于学习C语言中的字符串数据结构,可以通过学习字符数组的操作和使用标准库函数来实现字符串操作,进一步了解字符串的原理及在顺序和链表中的实现。参考资料中提供了关于字符串的原理及实现的详细内容,可以深入了解字符串的相关知识。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [[简述]数据结构-字符串(C语言实现)](https://blog.csdn.net/second60/article/details/80044985)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [c语言之数据结构实现的字符串](https://blog.csdn.net/weixin_45446903/article/details/97607846)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值