Codeforces Round #418 (Div. 2) C. An impassioned circulation of affection

题目链接:

http://codeforces.com/contest/814/problem/C

题意:

给出一个长为n的字符串s,接下来有q次询问,每次询问给出正整数m和字符c,问在字符串中最多添加m个字符c后字符串中最长的仅含c的连续子串的长度为多少

题解:

因为q<=2e5所以易想到这题需要将答案保存到数组中,这样就需要dp处理字符串

设dp[i][j][k]为从第i个下标开始选择修改k个字符后,仅含字符'a'+j的连续子串的最长长度为多少。

当i>=1,dp[i][j][k] = dp[i-1][j][k-p]       (当s[i]=='a'+j时p=0,否则p=1)

当i==0,dp[i][j][k] = q        (当k大于0或s[i]=='a'+j时q=1否则q=0)

然后因为给出m与c后dp的第一位无意义,所以可以舍去将dp[i][j][k]中有用的信息保存为ans[i][j],ans[i][j]表示修改i个字符为'a'+j字符后字符串的仅含'a'+j的连续子串最长长度


#include<bits/stdc++.h>
using namespace std;
#define MAX_N 40005
#define inf 0x3f3f3f3f
#define LL long long
#define uLL unsigned long long
const LL mod = 1e9+7;
const LL INF = 1e18;
typedef pair<int, int>P;
const double eps = 1e-6;

int dp[1505][26][1505];
int ans[1505][26];
int main()
{
    int n;
    scanf("%d", &n);
    char s[1505];
    scanf("%s", s);
    memset(dp, 0, sizeof(dp));
    memset(ans, 0, sizeof(ans));
    for(int i=0; i<n; i++) {
        for(int j=0; j<26; j++) {
            for(int k=0; k<=n; k++) {
                if(i) {
                    if(k)
                        dp[i][j][k] = dp[i-1][j][k-(s[i]!=('a'+j))] + 1;
                    else
                        dp[i][j][k] = (s[i]=='a'+j)?(1 + dp[i-1][j][k]):0;
                }
                else {
                    if(s[i]=='a'+j)
                        dp[i][j][k] = 1;
                    else
                        dp[i][j][k] = (k>0);
                }
            }
        }
    }
    for(int i=0; i<26; i++) {
        for(int j=0; j<n; j++) {
            for(int k=0; k<=n; k++) {
                ans[k][i] = max(ans[k][i], dp[j][i][k]);
            }
        }
    }
    int q;
    scanf("%d", &q);
    while(q--) {
        int m;
        char c;
        scanf("%d %c", &m, &c);
        printf("%d\n", ans[m][c-'a']);
    }
}



再提供另一种尺取法,更好编码和理解

#include<bits/stdc++.h>
using namespace std;
#define MAX_N 40005
#define inf 0x3f3f3f3f
#define LL long long
#define uLL unsigned long long
const LL mod = 1e9+7;
const LL INF = 1e18;
typedef pair<int, int>P;
const double eps = 1e-6;

int dp[26][1505];
int n, q;
string s;
void init()
{
    for(int i=0; i<26; i++) {
        for(int j=1; j<=n; j++) {
            char c = ('a'+i);
            int l = 0;
            int r = 0;
            int tmp = s[0]!=c;
            int ans = 0;
            while(r>=l && r<n) {
                if(j>=tmp)
                    ans = max(ans, r-l+1);
                if(j>=tmp) {
                    r++;
                    tmp += (s[r]!=c);
                }
                else {
                    tmp -= (s[l]!=c);
                    l++;
                }
            }
            dp[i][j] = ans;
        }
    }
}
int main()
{
    cin >> n;
    cin >> s;
    cin >> q;
    init();
    while(q--) {
        int m;
        char c;
        scanf("%d %c", &m ,&c);
        printf("%d\n", dp[c-'a'][m]);
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值