problem
https://www.nowcoder.com/acm/contest/79/C
给你一个长度为n且由a和b组成的字符串,你可以删除其中任意的部分(可以不删),使得删除后的子串“变化”次数小于等于m次且最长。
变化:如果a[i]!=a[i+1]则为一次变化。(且新的字符串的首字母必须是’a’)
如果初始串全为b,则输出0。
输入描述
第一行输入两个数n,m。(1 <= n <= 105,0 <= m <= 10)
第二行输入一行长度为n且由a和b组成的字符串
输出描述
输出一个数字表示最长长度
输入
8 2
aabbabab
输出
6
说明
原串可以变成aabbbb,只改变了一次,且长度最长。
思路
DP
见注释
代码示例1
#include<bits/stdc++.h>
using namespace std;
int n,m;
const int maxn=1e5+10;
const int inf=0x3f;
//i j 表示长度为i 变化次数不超过j
int a[maxn][12];//以a结尾
int b[maxn][12];//以b结尾
char str[maxn];
int main()
{
//freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);
cin>>n>>m;
cin>>str;
memset(b,-inf,sizeof(b));//不能以b开头 即b只能由a更新过来
for(int i=0;i<n;++i){
for(int j=0;j<=m;++j){
a[i+1][j]=a[i][j];//结尾不变的话 先等于了 这个有两种情况变大 ①后面不同 j+1 ② 后面相同直接+1
b[i+1][j]=b[i][j];
if(str[i]=='a'){
for(int j=0;j<=m;++j){
a[i+1][j+1]=max(a[i+1][j+1],b[i][j]+1);
a[i+1][j]=max(a[i+1][j],a[i][j]+1);
}
}
else{
for(int j=0;j<=m;++j){
if(a[i][j]>0){
b[i+1][j+1]=max(b[i+1][j+1],a[i][j]+1);
}
b[i+1][j]=max(b[i+1][j],b[i][j]+1);
}
}
}
}
cout<<max(a[n][m],b[n][m])<<endl;
return 0;
}
代码示例2
//qls
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int n,m;
char str[maxn];
int dp[maxn][12][2];
int main()
{
scanf("%d %d %s",&n,&m,str+1);
for(int i=n;i>=1;--i){
for(int j=0;j<=m;++j){
for(int k=0;k<2;++k){
dp[i][j][k]=max(dp[i+1][j][k],dp[i][j][k]);
int tk=str[i]-'a',tj=j+(k!=tk);
if(tj<=m) dp[i][tj][tk]=max(dp[i][tj][tk],dp[i+1][j][k]+1);
}
}
}
int ans=0;
for(int i=0;i<=m;++i){
ans=max(ans,dp[1][i][0]);
}
printf("%d\n",ans);
return 0;
}
为什么我会写出这样的代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
const int maxn=1e5+10;
const int inf=0x3f;
char str[maxn];
char str1[maxn];
int dp[maxn][12];//长度为i 翻转次数最多为j 最长的串的长度
int dfs(int i,int j)
{
cout<<i<<' '<<j<<endl;
if(dp[i][j]!=-1) return dp[i][j];
//边界
if(j==0) return dp[i][j]=-inf;
if(i==1) return dp[i][j]=1;
if(str1[i-1]!=str1[i-2]){
//删还是不删
int tp1;
char tp=str1[i-1];
str1[i-1]=str1[i];
if(str1[i-1]==str1[i-2]) tp1=dfs(i-1,j);
else tp1=dfs(i-1,j-1);
str1[i-1]=tp;
return dp[i][j]=max(max(tp1,dfs(i-1,j-1)+1),dp[i][j]);
}
else return dp[i][j]=max(dfs(i-1,j)+1,dp[i][j]);
}
int main()
{
ios::sync_with_stdio(false);
freopen("in.txt","r",stdin);
cin>>n>>m;
cin>>str;
memset(dp,-1,sizeof(dp));
int k=n;
for(int i=0;i<n;++i)
if(str[i]=='a'){
k=i;
break;
}
//全b
if(k==n){
cout<<0<<endl;
return 0;
}
for(int i=k;i<n;++i) str1[i-k]=str[i];
//str1 dp 长度n-k
for(int i=0;i<=m;++i){
dfs(n-k,i);
}
int ans=-inf;
for(int i=0;i<=m;++i)
ans=max(ans,dp[n-k][i]);
cout<<ans+k<<endl;
return 0;
}