Codeforces Round #442 (Div. 2) B.Nikita and string

以前立志要跟鸡老师学dp,结果中途而废。隔了三个月然后这道1500的dp做不出来。。。

题目链接:http://codeforces.com/contest/877/problem/B
思路一:存a和b的前缀数目。
那我们可以枚举所有中间区间[i,j]
a:[0-i] b:[i-j] a:[j-n] 把每个区间对应的值加起来。取最大值!妙啊!

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

int a[5005],b[5005];
int main(){
    IO;
    string s;cin>>s;
    int n = s.size();
    forn(i,s.size()){
        if(i) b[i+1] = b[i],a[i+1] = a[i];
        if(s[i]=='b') b[i+1]++;
        else a[i+1]++;
    }
    int ans = 0;
    for1(i,n){
        for(int j = i;j<=n;j++){
            int x = b[j]-b[i-1]+a[i-1]+a[n]-a[j];
            ans = max(x,ans);
        }
    }
    ans = max(ans,a[n]);
    cout <<ans<<'
';
    return 0;
}

思路二:dp
三个dp数组
0存的是a的最大长度
1存的是ab的最大长度
2存的是aba的最大长度

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
int dp[5005][3];
int main(){
    IO;
    string s;cin>>s;
    int n = s.size();
    forn(i,n){
        if(s[i]=='a'){
            dp[i+1][0] = dp[i][0]+1;
            dp[i+1][1] = max(dp[i][1],dp[i][0]+1);
            dp[i+1][2] = max(dp[i][2]+1,dp[i][1]+1);
        }
        else{
            dp[i+1][0] = dp[i][0];
            dp[i+1][1] = max(dp[i][1]+1,dp[i][0]);
            dp[i+1][2] = max(dp[i][2],dp[i][1]+1);
        }
    }
    cout << max({dp[n][0],dp[n][1],dp[n][2]})<<'
';
    return 0;
}
人一我百,人十我万。
原文地址:https://www.cnblogs.com/AlexPanda/p/12520329.html