前言

这道题去年参加蓝桥的时候我就做过了,但是因为c/c++对于字符串的支持不是很好(主要还是菜)一直没做出来,昨天下定决心把这道题给过了,这道题其实不是很难,但是对于细节的处理特别麻烦,为此,我写了好几个方法去实现它。

题目链接

分析

我们先来看下输入输出的样例,题目描述可以打开上面的那个链接查看:

1
2
3
输入1:
1 2 1
abcs-w1234-9s-4zz
1
2
输出1:
abcsttuuvvw1234556677889s-4zz
1
2
3
输入2:
2 3 2
a-d-d
1
2
输出2:
aCCCBBBd-d

这道题可以说是考细节方面的处理的,我到最后一直有两个点过不去,后来下载数据发现我没有考虑到数字0-9的情况,也就是checkLianXu这个函数。所以一定要理清思绪再来,不然会很懵逼的。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import java.util.Scanner;

/**
* Created By XuanRan on 2021/12/11
*/
public class P1098字符串的展开 {
public static int P1, P2, P3;
public static String data;

public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
P1 = sc.nextInt();
P2 = sc.nextInt();
P3 = sc.nextInt();
data = sc.next();

for (int i = 0; i < data.length(); i++) {
char c = data.charAt(i);
if (c == '-') {

if (i - 1 < 0 || i + 1 >= data.length()) {
System.out.print('-');
continue;
}

char s = data.charAt(i - 1);
char e = data.charAt(i + 1);

if (checkXiangLin(s, e)) {
continue;
}

if (!checkLianXu(s, e)) {
System.out.print('-');
continue;
}
if (P3 == 1) {
System.out.print(reverseStringForward(s, e, P2, P1));
continue;
} else {
System.out.print(reverseStringReverse(s, e, P2, P1));
continue;
}
}
System.out.print(c);
}

}

private static boolean checkXiangLin(char s, char e) {
int startASCII = (int) s;
int endASCII = (int) e;

return startASCII + 1 == endASCII;
}

/**
* 返回连续的字符
*
* @param s 从哪个字符开始
* @param e 哪个字符结束
* @param count 单个字符重复几次
* @param type 填充类型
* 1 小写
* 2 大写
* 3 *
* @return 结果
*/
public static String reverseStringForward(char s, char e, int count, int type) {
StringBuilder sb = new StringBuilder();
int startASCII = (int) s;
int endASCII = (int) e;

for (int i = s + 1; i <= e - 1; i++) {
for (int j = 1; j <= count; j++) {
char c = (char) i;
if (type == 1) { //小写模式
if (!isNum(c)) {
if (!isCapital(c)) c = (char) (c + 32); //大写转小写
}
} else if (type == 2) {
if (!isNum(c)) {
if (isCapital(c))
c = (char) (c - 32);
}
} else if (type == 3) {
c = '*';
}
sb.append(c);
}
}
return sb.toString();
}

private static boolean isNum(char c) {
return (c >= 49 && c <= 57);
}

/**
* 返回连续的字符
*
* @param s 从哪个字符开始
* @param e 哪个字符结束
* @param count 单个字符重复几次
* @param type 填充类型
* 1 小写
* 2 大写
* 3 *
* @return 结果
*/
public static String reverseStringReverse(char s, char e, int count, int type) {
StringBuilder sb = new StringBuilder();
int startASCII = (int) s;
int endASCII = (int) e;

for (int i = e - 1; i >= s + 1; i--) {
for (int j = 1; j <= count; j++) {
char c = (char) i;
if (type == 1) { //小写模式
if (!isNum(c)) {
if (isCapital(c)) c = (char) (c + 32); //大写转小写
}
} else if (type == 2) {
if (!isNum(c)) {
if (isCapital(c))
c = (char) (c - 32);
}
} else if (type == 3) {
c = '*';
}
sb.append(c);
}
}
return sb.toString();
}

/**
* 检查字符是大写的还是小写的
*
* @param c 要检查的字符
* @return 大写 true
* 小写 false
*/
public static boolean isCapital(char c) {
return !(c >= 49 && c <= 57);
}

public static boolean checkLianXu(char s, char e) {
int startASCII = (int) s;
int endASCII = (int) e;

if ((endASCII <= startASCII || startASCII + 1 == endASCII)) { //检查是否符合重复标准
return false;
}

return (startASCII >= 48 && endASCII <= 57) || (startASCII >= 65 && endASCII <= 65 + 32) || (startASCII >= 97 && endASCII <= 97 + 35);
}
}

代码应该不难理解,我把主要的部分划分成了几个函数,分别是:

  • checkLianXu 检查是否符合连续性规则(那两个点就是栽倒数字0-9中的0了)
  • isCapital 检查当前字符是大写的还是小写的
  • reverseStringReverse 反向生成字符串,参数具体是什么方法头已经写了
  • checkXiangLin 主要检查两个字符是否是相邻的,也就是0-1这种情况
  • reverseStringForward 正向生成字符串

对了,main方法里面的for循环题内的i - 1 < 0 || i + i >= data.length()主要是检查数据开头和结尾是否包含-这个字符。

结语

明天见。