• 牛客网 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 }
  • 相关阅读:
    【luogu】P1772物流运输(最短路+DP)
    【Bzoj】1001狼抓兔子(平面图最小割转对偶图最短路)
    后记
    【Luogu】P2680运输计划(树上差分+二分)
    【Luogu】P2059卡牌游戏(概率DP)
    【Luogu】P2051中国象棋(DP)
    概率与期望学习笔记
    【Luogu】P2894酒店Hotel(线段树)
    21.Mysql Server优化
    20.Mysql锁机制
  • 原文地址:https://www.cnblogs.com/taozi1115402474/p/8637047.html
Copyright © 2020-2023  润新知