CF1131E String Multiplication 题解

关于发现调了两个小时的题被学长场切了

一些结论

翻一下题面给出的“乘法”,其实就是把一个字符串重复插入到另一个字符串中
首先可以发现,除了 \(p_n\) ,其他字符串至多只有1的权值,所以我们先考虑 \(p_n\)
可以想到,相乘只会让字符串前缀权值或者后缀权值变大,也就是说相乘后会有变化的地方只有前缀和后缀
进一步可以想到,如果该字符串并非整个串都是同一个字符,那么该字符串首位相连之后就不会再变化了
所以考虑整个字符串字符相同的时候,就直接把 \(p_n\) 按题意乘到 \(p_{n-1}\) 里面,再按一般的方法处理
注:图片中从上到下插入,根据题意实际上是从下到上乘
IGuGSP.png

做法

  • 倒序考虑这个式子,首先处理 \(p_n\)
  • 如果这个字符串并不是整个串都相等的,就考虑直接在其中找一个合法子序列
  • 然后考虑前后缀,如果前后缀是同一个字符,那么就在前面的字符串中找到一个一样的字符,用来把前后缀接在一起,前后缀不相同时也是一样
  • 如果整个串都相同,那么就把它和上一个串合并(因为如果整个串都相同,其实这个串性质和一个字符差不多)
  • 而对于递归到的串,也和上面的法则一样处理——连接前后缀、合并,用一个简单的乘法原理就能统计答案了
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#define ll long long
using namespace std;
char c[100001];
vector<char>ch[100100];
ll n,len,a[100001],ans(1),m;
bool pool[100001][30];

void dfs(ll dep,char sam='\0'){
    if(dep<1)return ;
    ll g=ch[dep].size();
    for(ll i=1;i<=g;i++)a[i]=0;
    for(ll i=0;i<=ch[dep].size();i++)c[i+1]=ch[dep][i];
    for(ll i=1;i<=g;i++){
        if(sam=='\0'||c[i]==sam){
            ll j=i;
            for("lmh qs rrd";j<=g;j++)
                if(c[i]!=c[j])break;
            j--;
            for(ll k=i;k<=j;k++)a[k]=j-i+1;
            ans=max(ans,(j-i+1)+len*(j-i+2));
            i=j;
        }
    }
    if(sam=='\0')sam=c[1];
    if(a[1]!=g){
        if(c[1]==c[g]){
            // ans=max(ans,(a[1]+a[g])+(a[1]+a[g]+2)*len);
            for(ll i=1;i<dep;i++)
                for(ll j=0;j<=ch[i].size();j++)
                    if(ch[i][j]==sam)ans=max((a[1]+a[g])+(a[1]+a[g]+2)*len+1,ans);
        }
        else {
            for(ll i=1;i<dep;i++)
                for(ll j=0;j<=ch[i].size();j++)
                    if(ch[i][j]==sam)ans=max(ans,1+(a[1]+1)*len+a[1]);
            for(ll i=1;i<dep;i++)
                for(ll j=0;j<=ch[i].size();j++)
                    if(ch[i][j]==sam)ans=max(ans,1+a[g]+(a[g]+1)*len);
        }
    }
    else {
        len=g+(g+1)*len;
        dfs(dep-1,c[1]);
    }
}

int main(){
    scanf("%lld",&n);
    for(ll i=1;i<=n;i++){
        cin>>c+1;
        m=strlen(c+1);
        for(ll j=1;j<=m;j++)
            ch[i].push_back(c[j]);
    }
    dfs(n);
    cout<<ans;
    return 0;
}
posted @ 2021-11-08 17:14  蒟蒻丁  阅读(35)  评论(0编辑  收藏  举报