xtu oj 字母序列
文章目录
- 回顾
- 思路
- 代码
回顾
- A+B III
- 问题 H: 三角数
- 问题 G: 3个数
- 等式 数组下标查询,降低时间复杂度
- 1405 问题 E: 世界杯
- xtu 数码串
- xtu oj 神经网络
- xtu oj 1167 逆序数(大数据)
- xtu oj 原根
- xtu oj 不定方程的正整数解
- xtu oj 最多的可变换字符串
- xtu oj String I
思路
感觉应该是要用字符串的函数,strcpy
之类的,不能像我之前一样用数组去自己模拟,直接用封装好的会方便很多。
左移的时候可以发现,原来的字符串的字母的先后顺序其实是有规律的变化,比如说本来是 ABCD
,左移 2
之后变成 CDAB
,内部一小部分其实是没有变化的,CD
和 AB
的内部顺序没有变化,只是这两个部分的顺序交换了一下。所以左移的时候,还是拿前面说的这个来举例子,就是前面两个字母按照原来的顺序放到后面,第三个字母到最后一个字母放到前面。这里我得查一下 strcpy
的一些参数是啥了,不然就得数组模拟去实现,比较麻烦。
没找到我想要的参数的那种函数。我再去课件里面找一下试试。原来还是自己用数组写一个比较方便。
右移也是同样的情况。就是移位的那个数字作为分界点,把字符串分成两个部分,假设叫做 jjj
和 ttt
,jjj
内部顺序不变, ttt
内部的顺序也不变,但是 jjj
和 ttt
的顺序要交换,就像是这样子,本来是 jjjttt
这样子排列的,现在变成了 tttjjj
这样子排列的。
找了一下,有一个字符串拼接的函数,笔者之前没掌握到位。但是我强烈建议即将参加 c
语言考试的朋友学一下 strcat
等常见的字符串函数的用法,因为我印象中字符串的题,在考试的时候很可能会用这些函数就能很快地解决这类型的题,笔者在考场上用数组不停捣鼓,还是比较狼狈的。这里贴一个链接,大家可以去看一下,学习一下。全网最详细的字符串函数介绍—strcpy、strcat、strcmp
有时候不记得参数是啥,看编辑器也能有一些提示,确实遇事不慌,多观察已有的信息可能会有一些收获。dest
就是 destination
的英文缩写,一目了然。
本来以为一份代码能直接过,结果编译错误了。不知道是啥问题。
#include<stdio.h>
#include<math.h>
#include<string.h>int main(){//t 表示样例的个数int t;scanf("%d",&t);for(int times=1;times<=t;times++){//按照格式输出是第几个样例printf("#%d:\n",times);//表示字符的字母个数和操作的次数int n,cnt;scanf("%d%d",&n,&cnt);//存字符串,ABCD这种char hhh[30];for(int i=0;i<30;i++){if(i<26){hhh[i]='A'+i;}else{hhh[i]='\0';}}for(int i=0;i<cnt;i++){int op;scanf("%d",&op);if(op==0){//表示不需要移动
// printf("%s\n",hhh);for(int j=0;j<n;j++){printf("%c",hhh[j]);}puts("");}else if(op<0){//表示左移//临时存左边部分的字符串,用 60 的原因是,方便存,奥其实 30 完全够了,我傻了char jjj[30];//为了结构清晰一些,这里是分开写的,本来可以和 ttt 数组一块初始化的,请见谅for(int j=0;j<30;j++){jjj[j]='\0';}for(int j=0;j<abs(op);j++){jjj[j]=hhh[j];}//临时存右边部分的字符串char ttt[30];for(int j=0;j<30;j++){ttt[j]='\0';}//注意这里下标要从0开始,不能从 abs(op) 开始作为 ttt 的下标开始存,需要注意一下int cnt=0;for(int j=abs(op);j<n;j++){ttt[cnt++]=hhh[j];}//把临时的字符串放回原来的字符串数组//先拼接,再复制,应该没啥问题。然后输出。我这里分情况输出了,事实上可以全部判断结束之后输出的,可以减少一点代码量,无所谓了。strcat(ttt,jjj);strcpy(hhh,ttt);
// printf("%s\n",hhh);for(int j=0;j<n;j++){printf("%c",hhh[j]);}puts("");}else{//临时存左边的字符串char jjj[30];for(int j=0;j<30;j++){jjj[j]='\0';}int len=n-op;for(int j=0;j<len;j++){jjj[j]=hhh[j];}//临时存右边的字符串char ttt[30];for(int j=0;j<30;j++){ttt[j]='\0';}int cnt=0;for(int j=len;j<n;j++){ttt[cnt++]=hhh[j];}//和上面一样的过程,把字符串整个到一块strcat(ttt,jjj);strcpy(hhh,ttt);
// printf("%s\n",hhh);for(int j=0;j<n;j++){printf("%c",hhh[j]);}puts("");}}}return 0;
}
好像不是代码的问题,是头文件的问题, math
里面调用不了 abs
,我真是服了。加了一个头文件之后过了。
还有一个点,前面写思路的时候可能没写清楚,就是先把字符串分成两个部分,然后再把这两个部分交换顺序拼接在一起,因为下一次操作要在上一次操作的基础上进行,所以我们要把拼接好的字符串复制到原来的字符串数组。
代码
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>int main() {//t 表示样例的个数int t;scanf("%d", &t);for (int times = 1; times <= t; times++) {//按照格式输出是第几个样例printf("#%d:\n", times);//表示字符的字母个数和操作的次数int n, cnt;scanf("%d%d", &n, &cnt);//存字符串,ABCD这种char hhh[30];for (int i = 0; i < 30; i++) {if (i < 26) {hhh[i] = 'A' + i;}else {hhh[i] = '\0';}}for (int i = 0; i < cnt; i++) {int op;scanf("%d", &op);if (op == 0) {//表示不需要移动
// printf("%s\n",hhh);for (int j = 0; j < n; j++) {printf("%c", hhh[j]);}puts("");}else if (op < 0) {//表示左移//临时存左边部分的字符串,用 60 的原因是,方便存,奥其实 30 完全够了,我傻了char jjj[30];//为了结构清晰一些,这里是分开写的,本来可以和 ttt 数组一块初始化的,请见谅for (int j = 0; j < 30; j++) {jjj[j] = '\0';}for (int j = 0; j < abs(op); j++) {jjj[j] = hhh[j];}//临时存右边部分的字符串char ttt[30];for (int j = 0; j < 30; j++) {ttt[j] = '\0';}//注意这里下标要从0开始,不能从 abs(op) 开始作为 ttt 的下标开始存,需要注意一下int cnt = 0;for (int j = abs(op); j < n; j++) {ttt[cnt++] = hhh[j];}//把临时的字符串放回原来的字符串数组//先拼接,再复制,应该没啥问题。然后输出。我这里分情况输出了,事实上可以全部判断结束之后输出的,可以减少一点代码量,无所谓了。strcat(ttt, jjj);strcpy(hhh, ttt);// printf("%s\n",hhh);for (int j = 0; j < n; j++) {printf("%c", hhh[j]);}puts("");}else {//临时存左边的字符串char jjj[30];for (int j = 0; j < 30; j++) {jjj[j] = '\0';}int len = n - op;for (int j = 0; j < len; j++) {jjj[j] = hhh[j];}//临时存右边的字符串char ttt[30];for (int j = 0; j < 30; j++) {ttt[j] = '\0';}int cnt = 0;for (int j = len; j < n; j++) {ttt[cnt++] = hhh[j];}//和上面一样的过程,把字符串整个到一块strcat(ttt, jjj);strcpy(hhh, ttt);// printf("%s\n",hhh);for (int j = 0; j < n; j++) {printf("%c", hhh[j]);}puts("");}}}return 0;
}