牛客网 Wannafly挑战赛12 删除子串(线性dp)

题目描述

给你一个长度为n且由a和b组成的字符串,你可以删除其中任意的部分(可以不删),使得删除后的子串“变化”次数小于等于m次且最长。
变化:如果a[i]!=a[i+1]则为一次变化。(且新的字符串的首字母必须是'a')
如果初始串全为b,则输出0。

输入描述:

第一行输入两个数n,m。(1 <= n <= 105,0 <= m <= 10)
第二行输入一行长度为n且由a和b组成的字符串

输出描述:

输出一个数字表示最长长度

示例1

输入

8 2
aabbabab

输出

6

说明

原串可以变成aabbbb,只改变了一次,且长度最长。

题意

如上

题解

一看到这题就是Dp题,从变化次数m切入

这里j指变化次数,数组a是指最后放的是字符a的长度,b同理

a[j]=max(a[j]+1,b[j-1]+1),s[i] = 'a'(1<=j<=m+1)

b[j]=max(b[j]+1,a[j-1]+1),s[i] = 'b'

上面的意思是,如果s[i] = ‘a’,a[j]直接加上去,或者由b[j-1]通过变化加上去

这里由于新的字符串要求以‘a’开头,所以假设新串以‘b’通过变化得到为开始点

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     int n,m,a[11],b[11];
 6     char s[100005];
 7     for(int i=0;i<=10;i++)
 8         a[i]=b[i]=-1e9;
 9     cin>>n>>m;
10     m++;b[0]=0;
11     scanf("%s",s+1);
12     for(int i=1;i<=n;++i)
13         for(int j=m;j;--j)
14             if(s[i]=='a')
15                 a[j]=max(a[j]+1,b[j-1]+1);
16             else
17                 b[j]=max(b[j]+1,a[j-1]+1);
18     int ans=0;
19     for(int i=m;i;--i)
20         ans=max(ans,max(a[i],b[i]));
21     cout<<ans;
22     return 0;
23 }
原文地址:https://www.cnblogs.com/taozi1115402474/p/8637047.html