UVa 11920 - 0 s, 1 s and ? Marks

链接

传送门

题意

给出一个由'0', '1', '?'组成的字符串,其中'?'既可以当做'0',也可以当做'1'。输出最短的最长连续相同的字符长度。

思路

预处理出每一段的字符和长度,然后对于'?',与前一段和后一段字符是否相同进行分类讨论。有个trick是当'?'的长度为1,且前后字符不同时要根据前后两段的长度进行判断。

代码

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
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int maxn = 1010;
char s[maxn], tp[maxn];
int l[maxn];

int main() {
int t, tt = 0;
scanf("%d", &t);
while (t--) {
scanf("%s", s);
int len = int(strlen(s)), n = 0;
tp[n] = s[0], l[n] = 0;
for (int i = 0; i < len; ++i) {
if (s[i] != tp[n]) {
++n;
tp[n] = s[i], l[n] = 0;
}
++l[n];
}
++n;
int ans = 1;
for (int i = 0; i < n; ++i) {
if (tp[i] != '?') {
ans = max(ans, l[i]);
continue;
}
if (i == 0 || i == n - 1) {
continue;
}
if (tp[i - 1] == tp[i + 1]) {
if ((l[i] & 1) == 0) {
ans = max(ans, 2);
}
} else {
if (l[i] & 1) {
if (l[i] != 1) {
ans = max(ans, 2);
} else {
if (l[i - 1] > l[i + 1]) {
++l[i + 1];
} else {
ans = max(ans, l[i - 1] + 1);
}
}
}
}
}
printf("Case %d: %d\n", ++tt, ans);
}
return 0;
}