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
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
可以使用动态规划算法来实现查找两个字符串中的最大公共子串。具体实现方法如下: 1. 定义一个二维数组dp,其中dp[i][j]表示以第一个字符串的第i个字符和第二个字符串的第j个字符结尾的最大公共子串的长度。 2. 初始化dp数组,将所有元素都赋值为0。 3. 遍历两个字符串,如果第一个字符串的第i个字符和第二个字符串的第j个字符相等,则dp[i][j] = dp[i-1][j-1] + 1,否则dp[i][j] = 0。 4. 在遍历的过程中,记录最大的dp[i][j]的值以及对应的i和j,即为最大公共子串的长度和结束位置。 5. 最后根据最大公共子串的长度和结束位置,可以得到最大公共子串的起始位置和内容。 下面是C语言实现代码: ```c #include <stdio.h> #include <string.h> void findMaxCommonSubstr(char* str1, char* str2) { int len1 = strlen(str1); int len2 = strlen(str2); int dp[len1+1][len2+1]; int maxLen = 0, endPos = 0; memset(dp, 0, sizeof(dp)); for(int i=1; i<=len1; i++) { for(int j=1; j<=len2; j++) { if(str1[i-1] == str2[j-1]) { dp[i][j] = dp[i-1][j-1] + 1; if(dp[i][j] > maxLen) { maxLen = dp[i][j]; endPos = i-1; } } else { dp[i][j] = 0; } } } if(maxLen == 0) { printf("No common substring found.\n"); } else { printf("The maximum common substring is \"%.*s\".\n", maxLen, str1+endPos-maxLen+1); } } int main() { char str1[] = "abcdefg"; char str2[] = "bcdehij"; findMaxCommonSubstr(str1, str2); return 0; } ``` 输出结果为: ``` The maximum common substring is "bcde". ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值