学校算法作业(五)——子串及逆序子串
又到了写算法作业的时间了,这周给的题还是有水准的。(可能是因为我没用函数的关系,写了好久)话不多说,上题。
其实就是输出集合的所有子集,加上逆序
让我们冷静的思考一下,这道题想要我们干什么,首先是要逆序,再就是找子串。好,逆序不是什么难事,那么我们来思考一下找有序子串。找有序子串,我们一般会一类一类找。打个比方
栗子:
字符串: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的关系 | 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; }
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 }
算法多艰,诸君共勉~~~