CF877B Nikita and string 题解 动态规划

题目链接:http://codeforces.com/problemset/problem/877/B

题目描述

有一天聪聪发现了一个只包含字符 "a" 和 "b" 的字符串。
聪聪认为如果一个字符串是美丽的,如果这个字符串可以被分割成连续的三段,其中第1段和第3段都是只包含 "a" 的字符串,第2段是只包含 "b" 的字符串。
聪聪想要通过删除一些字符(也有可以一个字符都不需要删)来让这个字符串变成美丽的。
但是聪聪不能调整字符串中字符的顺序。
请问他能够得到的美丽的字符串的最大长度是多少?
注:这里分成的三段子串可以是空串。举个例子:
对于字符串 "bba" ,它是美丽的,因为可以将它分成 ""、"bb"、"a"三段。

输入格式

输入的第一行包含一个字含有字符 "a" 或 "b" 的字符串,该字符串长度不超过 5000。

输出格式

输出聪聪能够获得的最长的美丽的字符串的长度。

样例输入1

abba

样例输出1

4

样例输入2

bab

样例输出2

2

样例解释

样例1中的字符串本身就是美丽的;
样例2中的字符串,你可以删除一个 "a" 或者一个 "b" 来让他变美丽。

题目分析

这道题目的解法:动态规划。
\(f[i][j]\) 表示当前在字符串 \(s[i]\) 位置,并且在第 \(j\) 段(\(j=0,1,2\) 分别表示第 \(1,2,3\) 段)所能够获得的美丽的字符串的最大长度。
那么:
如果 s[i] == 'b'

  • \(f[i][0] = f[i-1][0]\);
  • \(f[i][2] = f[i-1][2]\);
  • \(f[i][1] = max(f[i-1][0], f[i-1][1]) + 1\);

如果 s[i] == 'a':

  • \(f[i][0] = f[i-1][0] + 1\);
  • \(f[i][1] = f[i-1][1]\);
  • \(f[i][2] = max(f[i-1][1], f[i-1][2]) + 1\);

实现代码如下:

#include <bits/stdc++.h>
using namespace std;
#define MOD 1000000007LL
const int maxn = 5050;
int n, f[maxn][3];
string s;
 
int main() {
    cin >> s;
    n = s.length();
    f[0][0] = f[0][2] = (s[0] == 'a') ? 1 : 0;
    f[0][1] = 1 - f[0][0];
    for (int i = 1; i < n; i ++) {
        if (s[i] == 'b') {
            f[i][0] = f[i-1][0];
            f[i][2] = f[i-1][2];
            f[i][1] = max(f[i-1][0], f[i-1][1]) + 1;
        }
        else {
            f[i][0] = f[i-1][0] + 1;
            f[i][1] = f[i-1][1];
            f[i][2] = max(f[i-1][1], f[i-1][2]) + 1;
        }
    }
    cout << max(f[n-1][0], max(f[n-1][1], f[n-1][2]) ) << endl;
    return 0;
}
posted @ 2020-01-17 16:08  quanjun  阅读(167)  评论(0编辑  收藏  举报