C. Unstable String
题目大意:
思路解析:
如果 101这个字符,如果把他看成一个不稳定的字符串,那么它可以提供6的贡献,因为不稳定的字符串的任意长度的子字符串一定是不稳定的字符串。
如果 101这个字符,如果把它看出 1和01两个不稳定的字符串,那么它们只能提供4的贡献。
所以找到第一个规律,如果能合并为更长的字符串,则一定要将其合并。合并之后,并不会影响其他位置的答案。
由样例1可以知道,如果字符为0?10,那么它可以组成01和010即(0? 和 ?10)这两个不稳定的字符串,无其他更优先的组成方案,即可以看出,如果当前位是?,那么它可能可以提供两次答案。即两种接的方案。
则如何避免答案的重复计算? 010的贡献可以看作1+2+3,即当前是第几个加几,然后0?10的贡献则为 1223。问号处输出当前位最大的贡献,就可以避免重复输出问号的贡献。
代码实现:
import java.io.*;
import java.math.BigInteger;
import java.util.*;
public class Main {
static int mod = (int) 1e9 + 7;
static int n;
static char[] s;
public static void main(String[] args) throws IOException {
int t = input.nextInt();
for (int o = 0; o < t; o++) {
String str = input.next();
s = str.toCharArray();
n = s.length;
long ans = 0;
int[][] dp = new int[n][2];
dp[0][0] = s[0] == '0' || s[0] == '?' ? 1 : 0;
dp[0][1] = s[0] == '1' || s[0] == '?' ? 1 : 0;
for (int i = 1; i < n; i++) {
if (s[i] == '1'){
dp[i][1] = dp[i - 1][0] + 1;
} else if (s[i] == '0') {
dp[i][0] = dp[i - 1][1] + 1;
}else {
dp[i][0] = dp[i - 1][1] + 1;
dp[i][1] = dp[i - 1][0] + 1;
}
}
for (int i = 0; i < n; i++) {
ans += (Math.max(dp[i][0], dp[i][1]));
}
out.println(ans);
}
out.flush();
out.close();
br.close();
}
static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
static Input input = new Input(System.in);
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static class Input {
public BufferedReader reader;
public StringTokenizer tokenizer;
public Input(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream), 32768);
tokenizer = null;
}
public String next() {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
try {
tokenizer = new StringTokenizer(reader.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
}
public String nextLine() {
String str = null;
try {
str = reader.readLine();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return str;
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
public Double nextDouble() {
return Double.parseDouble(next());
}
public BigInteger nextBigInteger() {
return new BigInteger(next());
}
}
}