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;
}