zoukankan      html  css  js  c++  java
  • CF1131E String Multiplication(???)

    这题难度2200,应该值了。

    题目链接:CF原网

    题目大意:定义两个字符串 $s$ 和 $t$($s$ 的长度为 $m$)的乘积为 $t+s_1+t+s_2+dots+t+s_m+t$。定义一个字符串的美丽度为最长的相同字母连续子序列的长度。现在给出 $n$ 个字符串 $p_i$,问 $((p_1p_2)p_3)dots p_n$ 的美丽度。

    $1le nle 10^5,sum|p_i|le 10^5$。


    官方题解讲的很复杂,但看起来也就是个暴力大模拟,跟我的做法差不多。

    为叙述方便,令 $P_i=((p_1p_2)p_3)dots p_i$。

    我们现在考虑如何从 $P_{i-1}$ 转移到 $P_i$。

    对于每个 $P_i$,我们维护 $s[i][c]$ 表示 $P_i$ 中最长的连续 $c$ 的长度。

    先不考虑乘法,将 $s[i][c]$ 设为 $p_i$ 中的连续长度。

    定义 $lc$ 为 $p_i$ 最长的连续字母前缀,$rc$ 为最长的连续字母后缀。

    首先如果 $p_i$ 的首尾字母不相同,那么 $s[i][{p_i}_1]$ 就可以从 $lc+[P_{i-1} ext{中出现过}{p_i}_1]$ 更新(接在原来字符的后面组成)。$s[i][{p_i}_{|p_i|}]$ 同理。

    否则如果 $p_i$ 不由相同字母构成,那么:

    • 如果 $P_i$ 中出现过 ${p_i}_1$,$s[i][{p_i}_1]$ 就可以从 $lc+rc+1$ 更新。(前缀接在这个字符后面,前一个后缀接在这个字符前面)
    • 否则,$s[i][{p_i}_1]$ 就可以从 $max(lc,rc)$ 更新,这不会更优,可以省略。

    否则,就可以把 $s[i-1][{p_i}_1]$ 个 ${p_i}_1$ 拿出来,前后接上 $p_i$,那么 $s[i][{p_i}_1]$ 就可以从 $|p_i|(s[i-1][{p_i}_1]+1)+s[i-1][{p_i}_1]$ 更新。

    注意最后 $P_{i-1}$ 会被拆成一个个字符,他们对 $s[i]$ 的贡献就是每个字符有没有出现过,而不是出现次数。

    最后所有 $s[n][c]$ 的最大值就是答案。

    时间复杂度 $O(sum |p_i|)$。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> PII;
    const int maxn=100010;
    #define MP make_pair
    #define PB push_back
    #define lson o<<1,l,mid
    #define rson o<<1|1,mid+1,r
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
    #define MEM(x,v) memset(x,v,sizeof(x))
    inline int read(){
        char ch=getchar();int x=0,f=0;
        while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
        while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
        return f?-x:x;
    }
    int n,cont[100010][26],s[26];
    char str[maxn];
    inline void chkmax(int &x,int y){
        if(y>x) x=y;
    }
    int main(){
        n=read();
        FOR(nn,1,n){
            scanf("%s",str+1);
            int len=strlen(str+1);
            int cnt=1;
            FOR(i,1,len)
                if(str[i]!=str[i+1]){
                    chkmax(cont[nn][str[i]-'a'],cnt);
                    cnt=1;
                }
                else cnt++;
            int lcnt=1,rcnt=1;
            FOR(i,2,len){
                if(str[i]==str[1]) lcnt++;
                else break;
            }
            ROF(i,len-1,1){
                if(str[i]==str[len]) rcnt++;
                else break;
            }
            if(nn!=1){
                if(lcnt==len && rcnt==len) chkmax(cont[nn][str[1]-'a'],len*(cont[nn-1][str[1]-'a']+1)+cont[nn-1][str[1]-'a']);
                else if(str[1]==str[len]){
                    if(cont[nn-1][str[1]-'a']) chkmax(cont[nn][str[1]-'a'],lcnt+rcnt+1);
                }
                else{
                    chkmax(cont[nn][str[1]-'a'],lcnt+!!cont[nn-1][str[1]-'a']);
                    chkmax(cont[nn][str[len]-'a'],rcnt+!!cont[nn-1][str[len]-'a']);
                }
            }
            FOR(i,0,25) chkmax(cont[nn][i],!!cont[nn-1][i]);
        }
        int res=0;
        FOR(i,0,25) res=max(res,cont[n][i]);
        printf("%d
    ",res);
    }
    View Code
  • 相关阅读:
    Visual Studio 常用快捷键 (二)
    Visual Studio 常用快捷键
    页游体验
    JSFL 工具
    GhostCat工具
    如何制作一个塔防游戏
    水墨
    给 想转2dx 却无从下手的aser
    两岸三地在线编程学习网站大全
    as3反射应用及简要代码
  • 原文地址:https://www.cnblogs.com/1000Suns/p/10424675.html
Copyright © 2011-2022 走看看