学校算法作业(五)——子串及逆序子串

  又到了写算法作业的时间了,这周给的题还是有水准的。(可能是因为我没用函数的关系,写了好久)话不多说,上题。

 

  其实就是输出集合的所有子集,加上逆序

 

让我们冷静的思考一下,这道题想要我们干什么,首先是要逆序,再就是找子串。好,逆序不是什么难事,那么我们来思考一下找有序子串。找有序子串,我们一般会一类一类找。打个比方

  栗子:

    字符串:ABCDE

    1、先找最长的ABCDE

    2、找第二长的ABCD   BCDE

    ……

    5、找最短的   A  B C D E

  以此类推。

字串寻找思路有了,那么想想怎么输出子串把。很显然,我们有i类,每一类有j个字串,每个子串长度为K;一看就有三个循环。那怎么控制控制变量呢?对于这种问题列个表格是最好的解决方案.

        下面->指向的方向

次数\ 循环变量 i j(范围) k (范围)
1 0 0->1

[0,3]ABCD

2 1 0->2

[0,2]ABC

[1,3]BCD

3 2 0->3

[0.1]AB

[1,2]BC

[2,3]CD

4 3 0->4

[0,0]A

[1,1]B

[2,2]C

[3,3]D

 

第一遍扫描过去 我们会发现 j 的最大值等于 i+1,我们可以很快捷的写出相应的语句。

for (int i = 0; i < len; i++)
{
    for (int j = 0; j < i + 1; j++)
    {
        ……//这里第三个循环后面推
    }
}

  现在我么们只剩下第三个循环了。让我们再来看看表格,很容易的我们又发现k的每一次循环范围都是上下限同时后移1位。这也意味着,我们k的初始值和循环终止条件,再每次开启新一轮循环时都会改变,而且步长为 1。我们再仔细化一下表格

  

次数\ 循环变量 i j j与k的关系
1 0 0->1 j = 0, k [0,3]

[0,3]ABCD

2 1 0->2

j = 0, k[0,2]

j = 1, k[1,3]

[0,2]ABC

[1,3]BCD

3 2 0->3

j = 0, k[0,1]

j = 1, k[1,2]

j = 2, k[2,3]

[0.1]AB

[1,2]BC

[2,3]CD

4 3 0->4 j = 0, k[0,0]

j = 1, k[1,1]

j = 2, k[2,2]

j = 3, k[3,3]

[0,0]A

[1,1]B

[2,2]C

[3,3]D

  这样我就清晰的发现 j 和 k 的 值是同步的。好了,现在只剩下 k 的结条件了。咋一眼看过去没什么规律是吧。让我们仔细观察一下 k 的值,是不是每一组的第一次终止条件都不一样。

从 3 -> 2 -> 1 -> 0. 每一类都减少1,即 i 上升 1 而 k 每一组的第一次终止条件都减少 1.然而这个规律仅仅是第一个结束条件.再根据刚刚的步长为1 的条件我就可以轻松的写出 i, j, k之间的关系式,即

k < len - i + j

 

这样我们就可以写出核心代码了

    for (int i = 0; i < len; i++)
    {
        for (int j = 0; j < i + 1; j++)
        {
            for (int k = j; k < len - i + j; k++)
            {
                printf("%c", str[k]);
            }
        }
    }

  逆序输出就把第三个循环的结束与开始换一换就行

最后贴代码

  记得自己先试一试!!!

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

#define MAXSIZE 110

int main()
{
    char str[MAXSIZE];
    char Rstr[MAXSIZE];
    scanf("%s", str);
    int len = strlen(str);

    for (int i = 0; i < len; i++)
    {
        for (int j = 0; j < i + 1; j++)
        {
            for (int k = j; k < len - i + j; k++)
            {
                printf("%c", str[k]);
            }
            printf(" ");
            for (int k = len - i + j - 1; k >= j; k--)
            {
                printf("%c", str[k]);
            }
            printf("\n");
        }
    }

    return 0;
}
O(2n^3)

 

2019-10-10 

更新一下用库函数的写法

 1 /**
 2  * @brief  字串以及逆序字串
 3  * @note   strrevn函数只在gcc中可用Linux和cb都是gcc的解释器
 4  * @author 杨文蓁的小迷弟
 5  */
 6 #include <stdio.h>
 7 #include <stdlib.h>
 8 #include <string.h>
 9 #include <stdbool.h>
10 #define MAXSIZE 101
11 
12 int main()
13 {
14     char ArrayStr[MAXSIZE];
15     scanf("%s", ArrayStr);
16     int len = strlen(ArrayStr);
17     SearchMax(ArrayStr, len);
18     return 0;
19 }
20 /**
21  * @brief  查找最大子串
22  * @note   非Kmp
23  * @param  *Original: 最短的输入字符串
24  * @param  ArrayStrSize: 字符串数组大小
25  * @retval 字串长度
26  * @author 杨文蓁的小迷弟
27  */
28 void SearchMax(char *Original, int ArrayStrSize)
29 {
30     int len = strlen(Original);
31     char Normal[MAXSIZE];
32     char Reversed[MAXSIZE]; //用来存储逆序
33 
34     //比较次数
35     for (int i = len; i >= 1; i--)
36     {
37         //从第j处开始取字串
38         for (int j = 0; j <= len - i; j++)
39         {
40             strncpy(Normal, Original + j, i);
41             strncpy(Reversed, Original + j, i);
42             Normal[i] = '\0';
43             Reversed[i] = '\0';
44             strrev(Reversed);
45             printf("%s %s\n", Normal, Reversed);
46         }
47     }
48 }
库函数

 

  算法多艰,诸君共勉~~~

posted @ 2019-09-29 21:46  秦_殇  阅读(226)  评论(0编辑  收藏  举报