http://codeforces.com/contest/877/problem/B
aとbからなる文字列Sがある。
この文字列から任意個数の文字列を抜いて、(任意個のa)(任意個のb)(任意個のa)の文字列を作る。
(任意個は0個でも良い)
作れる最大の文字数を求めよ。
len(S)≦5000
解法
http://codeforces.com/contest/877/submission/31636732
(任意個のb)の部分を全列挙して考える。
S[L,R]をbの部分と考えるとS[L,R]の'a'だけ抜くのが最適であり、前後のS[0,L-1]とS[R+1,N-1]は'b'だけ抜くのが最適である。
結局、抜いた後の文字列の長さは、(S[0,L-1]の'a'の個数)+(S[L,R]の'b'の個数)+([R+1,N-1]の'a'の個数)であるため、この最大値を求めれば答え。
個数計算を高速化しないと通らないが、累積和で計算できる。
「A[x] := S[0,x]の'a'の個数」としておくと、S[x,y]の'a'の個数は A[y]-A[x-1] で計算できる。
'b'も同様にやれば、区間の個数の取得はO(1)となって間に合う。
Hackポイントが(任意個のb)が0である場合も考慮する場合
string S; int A[5010], B[5010]; //--------------------------------------------------------------------------------------------------- void _main() { cin >> S; int N = S.length(); rep(i, 0, N) { if (S[i] == 'a') A[i] = 1; else B[i] = 1; } rep(i, 1, N) A[i] += A[i - 1]; rep(i, 1, N) B[i] += B[i - 1]; int ans = A[N-1]; rep(L, 0, N) rep(R, L, N) { int a = 0; if (L) a = A[L - 1]; int c = A[N - 1] - A[R]; int b = B[R]; if (L) b -= B[L - 1]; ans = max(ans, a + b + c); } cout << ans << endl; }