1. 程式人生 > 其它 >CF1131E String Multiplication 題解

CF1131E String Multiplication 題解

關於發現調了兩個小時的題被學長場切了

一些結論

翻一下題面給出的“乘法”,其實就是把一個字串重複插入到另一個字串中
首先可以發現,除了 \(p_n\) ,其他字串至多隻有1的權值,所以我們先考慮 \(p_n\)
可以想到,相乘只會讓字串字首權值或者字尾權值變大,也就是說相乘後會有變化的地方只有字首和字尾
進一步可以想到,如果該字串並非整個串都是同一個字元,那麼該字串首位相連之後就不會再變化了
所以考慮整個字串字元相同的時候,就直接把 \(p_n\) 按題意乘到 \(p_{n-1}\) 裡面,再按一般的方法處理
注:圖片中從上到下插入,根據題意實際上是從下到上乘

做法

  • 倒序考慮這個式子,首先處理 \(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;
}