zoukankan      html  css  js  c++  java
  • CF1537E2 Erase and Extend (Hard Version) 题解

    一、题目:

    codeforces原题

    洛谷原题

    二、思路:

    这题不知道为什么官方题解写得那么复杂。还需要用到扩展 KMP,即 Z 函数。感谢 Robert_JYH 巨佬提供的思路,让我明白了一种非常简单的做法。

    首先,我们可以证明,最优解一定是通过先执行操作 1,后执行操作 2 来得到的(当然也可以不进行操作 1,直接进行操作 2)。因为如果最优解是执行了一些操作 2 之后,再执行的操作 1,那么我们发现把操作 1 放到操作 2 之前操作一定会使答案变得不劣

    所以问题就转化成给定一个字符串 (s),需要保留 (s) 的一个前缀 (pre),同时让 (pre) 复制若干次,得到一个长度为 (k) 的字符串(多余的部分删去)。目标是让最终的字符串的字典序最小。

    暴力当然很简单了,我们枚举所有前缀 (pre),模拟这个过程,更新答案即可。你就可以成功地解决这道题的简单版了。

    那么现在来考虑线性的做法。

    我们设当前最优的前缀为 (s[0sim p-1]),现在枚举到的前缀是 (s[0sim i])。那么分为三种情况。(字符串的下标从 0 开始。)

    1. (s[i]>s[imod p]),那么非常遗憾,(i)(i) 以后的所有前缀均不能作为最优答案。直接跳出循环。
    2. (s[i]<s[imod p]),我们发现用前缀 (s[0sim i]) 比前缀 (s[0sim p-1]) 更优,于是令 (pgets i+1)
    3. (s[i]=s[imod p]),这并不能说明什么,我们只能什么都不做。

    然后呢?然后你就会惊奇的发现,你写完了一道 Div2 难度的第六题!

    三、代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    #define FILEIN(s) freopen(s".in", "r", stdin);
    #define FILEOUT(s) freopen(s".out", "w", stdout)
    #define mem(s, v) memset(s, v, sizeof s)
    
    inline int read(void) {
        int x = 0, f = 1; char ch = getchar();
        while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
        while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
        return f * x;
    }
    
    int n, K;
    string s;
    
    int main() {
        n = read(); K = read();
        cin >> s;
        int p = 1, i = 0, n = s.length();
        for (; i < n; ++ i) {
            if (s[i] > s[i % p]) break;
            if (s[i] < s[i % p]) p = i + 1;
        }
        for (i = 0; i < K; ++ i) putchar(s[i % p]);
        puts("");
        return 0;
    }
    

  • 相关阅读:
    顺便说说webservice
    了解c3p0,dbcp与druid
    静心己过
    慢慢来写SpringMVC基本项目
    关于druid的配置说明
    想法
    看见了别人的数据库题,随便写写
    Java 工具类
    Java 工具类
    使用JavaMail实现发送模板邮件以及保存到发件箱
  • 原文地址:https://www.cnblogs.com/little-aztl/p/14902671.html
Copyright © 2011-2022 走看看