【DP+思维】按序组合字符串 Codeforces Round #541 (Div. 2) E. String Multiplication

Codeforces Round #541 (Div. 2) E. String Multiplication

http://codeforces.com/contest/1131/problem/E

给你一个n(<=1e5)

给你n个字符串

保证所有字符串总和加起来<=1e5

每个字符串的组合规则是,

eg:

3

a

b

a

先变成bab,再变成abaaaba 最后最多有三个连续重复的字母,答案为3

所以我们可以发现如果母串的字符都是一样的,有y个,且子串有x个连续的这个字母

那么他们组成的这个字母的连续个数是x+(x+1)*y

当然也有可能这样子比原本母串连续的少,所以我们的dp式为

if(dp[i-1][j])
{
     if(pre[j]!=len) dp[i][j]=max(dp[i][j],pre[j]+sub[j]+1);
     else dp[i][j]=max(dp[i][j],dp[i-1][j]+(dp[i-1][j]+1)*dp[i][j]);
}

或者母串并不全都是一样的字母

比如xxyxx

那么如果子串中有x,则连续x字母个数为pre[x]+sub[x]+1;

不然的话就是该母串中最多连续的个数

 

 

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int dp[maxn][30],pre[30],sub[30],p[30],pre1[30];
char a[maxn];

void check(int f)
{
    memset(pre,0,sizeof pre);
    memset(sub,0,sizeof sub);
    memset(p,0,sizeof p);
    memset(pre1,0,sizeof pre1);
    scanf("%s",a+1);
    int len=strlen(a+1);
    int k=a[1]-'a'+1;
    p[k]++;
    for(int j=2; j<=len; j++)
    {
        k=a[j]-'a'+1;
        if(a[j]==a[j-1])
        {
            p[k]++;
        }
        else
        {
            int k1=a[j-1]-'a'+1;
            pre1[k1]=max(p[k1],pre1[k1]);
            p[k1]=0;
            p[k]++;
        }
    }
    pre1[k]=max(pre1[k],p[k]);
    for(int i=1;i<=26;i++)
    {
        dp[f][i]=pre1[i];
    }
    for(int j=1; j<=len; j++)
    {
        if(a[j]==a[1])
        {
            k=a[j]-'a'+1;
            pre[k]++;
        }
        else break;
    }
    for(int j=len; j>=1; j--)
    {
        if(a[j]==a[len])
        {
            k=a[j]-'a'+1;
            sub[k]++;
        }
        else break;
    }
    //cout<<dp[f][1]<<" "<<dp[f][2]<<" "<<dp[f][3]<<endl;
}


int main()
{
    int n;
    cin>>n;
    check(1);
    for(int i=2;i<=n;i++)
    {
        check(i);
        int len=strlen(a+1);
        for(int j=1;j<=26;j++)
        {
            if(dp[i-1][j])
            {
                if(pre[j]!=len) dp[i][j]=max(dp[i][j],pre[j]+sub[j]+1);
                else dp[i][j]=max(dp[i][j],dp[i-1][j]+(dp[i-1][j]+1)*dp[i][j]);
            }
        }
    }

    int ans=0;
    for(int i=1;i<=26;i++)
    {
        ans=max(ans,dp[n][i]);
    }
    cout<<ans<<endl;

    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值