C语言数组实现最大公共字符串

C语言数组实现最大公共字符串

关于最大公共字符串真的难为我这0基础的同学了,花了整整5个小时,爬了好几个帖子。

可是帖子里面的技术含量太高,看不懂的居多,有用指针的,有用strstr这个没有学过的函数的。指针变量虽然说能看懂一部分,但是还是有点吃力,后来看到一个帖子说用二维数组来计数,就看了一下,只可惜他并没有用纯数组来做。所以我就根据学过的C语言,花了近3个小时,写出了下面的这些代码。

//10、 找出多个字符串中的最大公共子字符串,如“nbitheimanb”和“itheia”的最大子串是:”ithei”。(C语言)

#include <stdio.h>

#include <string.h>

int main()

{

    //1.定义字符串数组

    char s1[100], s2[100];

    //2.定义一个二维数组存放指定变量(两个字母相等,值为1,不相等,值为0)

    int a[100][100];

    //3.定义变量记录公共字符串长度

    int MaxLenth = 0;

    //4.定义变量记录相等字符的最后的地址

    int adds = 0;

    //5.提示用户输入第一个字符串

    printf("请输入第一个字符串:\n");

    //6.接收用户输入的第一个字符串数组

    scanf("%s", s1);

    //7.提示用户输入第二个字符串

    printf("请输入第二个字符串\n");

    //8.接收用户输入的第二个字符串数组

    scanf("%s", s2);

    //9.遍历字符串s1

    for(int i = 0; i < strlen(s1); i++)

    {

        //10.遍历字符串s2

        for(int j = 0; j < strlen(s2); j++)

        {

            //11.判断相应字符是否相等

            if(s1[i] == s2[j])

            {

                //12.如果对应字符相等,则在二维数组对应坐标赋值为1

                a[i][j] = 1;

            }

            //13.如果对应字符不相等,则在二维数组对应坐标赋值为0

            else

                a[i][j] = 0;

        }

    }

    //14.打印说明

    printf("------------上方为输入数据-----------\n");

    printf("----------下方为二维数组数据-----------\n");

    //15.遍历输出二维数组(此处作为查看使用)

    for(int i = 0; i < strlen(s1); i++)

    {

        for(int j = 0; j < strlen(s2); j++)

        {

            printf("%d ",a[i][j]);

        }

        //16.每打印完一行,换行

        printf("\n");

    }

    //17.打印说明(分隔符)

    printf("----------下方为结果数据-----------\n");

    //18.遍历二维数组的行元素

    for(int i = 0; i < strlen(s1); i++)

    {

        //19.遍历二维数组的列元素

        for(int j = 0; j < strlen(s2); j++)

        {

            //20.判断该坐标处值是否为1,值为1代表是两个字符串开始字符开始相等的位置

            if(a[i][j] == 1)

            {

                //21.定义并初始化临时变量,记录存放公共字符串长度

                int temp = 0;

                //22.定义新的变量,存放i值,避免更改i值

                int i1 = i;

                //23.定义新的变量,存放j值,避免更改j值

                int j1 = j;

                //24.当该坐标的值为1时,进入循环,判断该坐标右下角坐标是否为1,如果为1,代表两个字符串下一个字符也相等

                while(a[i1][j1] == 1)

                {

                    //25.自增1,为下次判断做准备

                    i1++;

                    //26.自增1,为下次判断做准备

                    j1++;

                    //27.记录公共字符串的长度

                    temp++;

                }

                //28.判断新的公共字符串长度是否大于上一次公共字符串长度,如果不大于,则互换值。保证所取公共字符串的长度是最大。

                if(temp > MaxLenth)

                {

                    MaxLenth = temp;

                    //29.把最长公共字符串地址赋值给adds

                    adds = j1;

                }

            }

        }

    }

    //30.输出最大公共字符串长度值

    printf("最大公共字符串长度:%d\n",MaxLenth);

    //31.输出标题

    printf("最大公共字符串是:");

    //32.循环输出公共字符串

    for(int i = 0 ; i < MaxLenth; i++)

    {

        //33.因为所取地址值是最后的地址,所以要提取公共字符串的首字符地址,为 adds - MaxLenth

        printf("%c",s2[adds - MaxLenth +i]);

    }

    //34.输入换行符

    printf("\n");

    return 0;

}

试运行:     

请输入第一个字符串:

nbitheimanb

请输入第二个字符串

itheia

------------上方为输入数据-----------

----------下方为二维数组数据-----------

0 0 0 0 0 0

0 0 0 0 0 0

1 0 0 0 1 0

0 1 0 0 0 0

0 0 1 0 0 0

0 0 0 1 0 0

1 0 0 0 1 0

0 0 0 0 0 0

0 0 0 0 0 1

0 0 0 0 0 0

0 0 0 0 0 0

----------下方为结果数据-----------

最大公共字符串长度:5

最大公共字符串是:ithei

此理论是根据,使用二维数组存放0,1,对应字符串中的某个字符,把它s1位置作为横坐标,把它s2的位置作为纵坐标,在二维数组里面赋值。如果相等,赋值为1,如果不相等,赋值为0。在例子中可以看到,二维数组输出的结果。然后用for循环遍历二维数组,找出值为1的元素,当找到这个元素时,接着判断该元素的右下角的元素是否为1,如果为1,则计数,直到不为1退出。这步的作用,就是判断公共字符串的个数,至于怎么来判断的,大家可以看数组,顺序必须得时由左上角到右下角的斜线上相同为1,不能是其它的方向。看数组可以看到2、3、4、5、6行(首行为0行)对应的0、1、2、3、4列,值为1。那么在数组s1中的2、3、4、5、6号元素,和s2的0、1、2、3、4号元素就是公共字符串。如此判断,找出最长的一个,用adds记录最后一位元素的横坐标或者是纵坐标,在这里我记录的是纵坐标也就是s2数组元素序号。输出的时候注意,记录的时最后一位元素序号,所以要减去该字符长度,才是公共字符串首元素的序号,然后循环输出。

思路解析:

1、把两个字符串里面相等的字符和不相等的字符,转化为更好理解的数字形式,存放到二维数组。

2、建立一个二维数组,用来存放0和1,0代表该坐标处两个字符不相等,1代表该坐标出两个字符相等。

3、把其中一个字符串作为行元素,另外一个字符串作为列元素。在这里s1是行元素,s2是列元素。

4、用for循环遍历两个字符串,找出相等的元素,并按照行列坐标对应放到二维数组里面。

5、用for循环遍历二维数组,找出等于1的元素,当找到等于1的元素之后,重新定义两个变量,对应提取坐标(为了不改变for循环中i,j的值)。

6、定义全局变量MaxLenth,然后定义中间变量temp存放临时的公共字符串长度,用while循环判断横纵坐标同时增1,即从左上角到右下角的斜线上的元素是否相等,如果相等,中间变量自增1。把中间变量赋值给全局变量MaxLenth。

7、定义一个整型变量adds,存放找到的最后一个1的二维坐标中的纵坐标或者横坐标(代码中存放的时纵坐标)。

8、用if语句判断,新找到的公共字符串(斜线上连续为1的个数)长度是否大于上一个的长度,如果大于,把新值赋给全局变量MaxLenth,并把最新的纵坐标赋值给整形变量adds。如果不大于,继续循环寻找。

9、输出找到的最长的字符串个数即MaxLenth的值。

10、输出字符串:要输出的字符串的长度是MaxLenth,该字符串的末地址是adds,找出该字符串的首地址为adds – MaxLenth,用for循环输出该字符串。

补充:为什么只能在方向是左上角到右下角的斜线上寻找连续的1,因为如果是其它方向会导致寻找的1(相等字符)的顺序是反着的。

举例:如果是左下到右上,那么它的顺序是按照s1字符串的首字符开始与s2的末字符开始比较,然后s1增加,s2减少,那么得出的公共字符串是逆向的。

左上角到右下角和右下角到左上角是一条斜线,只不过是输出形式变化。读者可自行斟酌。

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值