[dp] 玩具

题目描述

儿时的玩具总是使我们留恋,当小皮还是个孩子的时候,对玩具更是情有独钟。小皮是一个兴趣爱好相当广泛且不专一的人,这这让老皮非常地烦恼。也就是说,小皮在不同时刻所想玩的玩具总是会不同,而有心的老皮也会尽量满足他的要求,帮他买一些新玩具。
一开始小皮有一个长度为\(N\)的玩具序列 , 小皮的玩具可以用\(a,b,c,...,z26\)个英文字母表示,小皮可能会有\(q\)种需求,每种需求可以用一个二元组\((x,y)\)表示代表在此时最喜欢\(x\)这种玩具,他希望老皮帮他买回\(y\)个玩具\(x\),小皮希望知道假如用这\(y\)个玩具去替换原来的玩具,最多可以产生多长的连续为\(x\) 的这种玩具的序列?

输入格式

第一行一个正整数\(N\),表示小皮有\(N\)个玩具
接来下一行一个由小写字母构成的字符串,表示初始的玩具序列。
接来下一行一个正整数\(q\), 表示小皮的\(q\)种需求
接下来\(q\)行,每行输入二元组\((x,y)\),含义如题目描述所述

输出格式

输出一共\(q\)行,表示每组询问的答案

样例输入

5
aabaa
2
a 1
b 2

样例输出

5
3

样例解释

对于第一组询问,我们可以把\(b\)替换为\(a\),那么连续为\(a\)的最长序列长度为5
对于第二组询问,我们可以把与\(b\)相邻的两个\(a\)替换为\(b\),那么连续为\(b\)的最长序列长度为3

数据范围

对于 10% 的数据:\(N,q<=10\)
对于 30% 的数据:\(N,q<=100\)
对于另外20%的数据:只存在\(a,b\)两种字符
对于100%的数据:\(N<=2000,q<=3*10^5,1<=y<=N\)
保证所有出现的字符都是小写字母.

题解

对于这道题,可以发现N的范围是可以接受\(N^2\)的,而q比较大,如果再套个什么东西很容T掉,所以我们选择在外面预处理,dp求出\(dp[i][j]\)表示把原串\(i\)个字符替换为\(j\)的最大长度
实现:\(N^2\)枚举每个子串,再在外面套一个枚举字母的循环,复杂度\(O(26*N^2)\)
所以总复杂度\(O(26*N^2+q)\)

#include<bits/stdc++.h>
#define Max(a,b) ((a)>(b)?(a):(b))
#define in(i) (i=read())
using namespace std;
inline int read() {
  int ans=0,f=1; char i=getchar();
  while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
  while(i>='0' && i<='9') {ans=(ans<<1)+(ans<<3)+(i^48); i=getchar();}
  return ans*f;
}
int n,m;
int dp[2010][30];
char s[2010];
void init() {
  for(int i=1;i<=26;i++) {
    for(int j=1;j<=n;j++) {
      int tq=0;
      for(int k=j;k<=n;k++) {
          if((s[k]-'a'+1)!=i) tq++;
          dp[tq][i]=Max(dp[tq][i],k-j+1);
      }
      for(int k=1;k<=n;k++) if(dp[k-1][i]>dp[k][i]) dp[k][i]=dp[k-1][i];//这里注意一下,因为题目要求替换的数量可能会大于需要替换的字符数量,比如样例中只有一个b,单若是题目要求替换两个a的没有这个更新就会WA
    }
  }
}
int main()
{
  //freopen("toy.in","r",stdin);
  //freopen("toy.out","w",stdout);
  in(n);scanf("%s",s+1);
  init();in(m);
  char t[2];int a;
  for(int i=1;i<=m;i++) {
    scanf("%s%d",t,&a);
    printf("%d\n",dp[a][t[0]-'a'+1]);
  }
}

博主蒟蒻,随意转载.但必须附上原文链接

http://www.cnblogs.com/real-l/

猜你喜欢

转载自www.cnblogs.com/real-l/p/9488193.html