• CF1527 E2. Erase and Extend (Hard Version)


    Problem - E2 - Codeforces

    题意:

    给出一个长为n的字符串,你可以进行2种操作

    1、把串在后面再拼接一次

    2、删去串的最后一个元素

    要求用这两种操作得出字典序最小的长为m的串

    首先答案肯定是由一个前缀拼接多次构成

    假设当前的最优前缀是A前缀,长度为LA,现在正在考虑的是B前缀

    1、如果s[B%LA]和s[A]一样,那么不用管继续往后走

    2、如果s[B%LA]比s[A]小,那么B前缀比A前缀更优秀

    3、如果s[B%LA]比s[A]大,那么A前缀比B前缀更优秀

    先来看2和3的正确性

    在1的条件下,他们都包含了s[0…A]拼接多次=s[0…B-1]

    所以只需要比较s[B%LA]与s[A]即可

    然后是1的正确性,它包含了s[0…A]拼接多次=s[0…B]

    令B%LA=t,可以把前B的字符分为3段

    s[0…t]一段记为X,s[t+1,LA-1]一段记为Y,s[LA…B]一段等同于s[0…t]

    如果还是用A前缀,那么拼接结果是XYXYXYXY

    如果改为用B前缀,那么拼接结果是XYXXYXXY

    所以如果YX<XY,那么还是原先的A前缀

    如果XY<YX,才会改用B前缀

    但是如果XY<YX,XY的拼接就不会是最小的,因为X的拼接会给更小

    #include<bits/stdc++.h>
     
    using namespace std;
     
    #define N 500003
     
    char s[N];
     
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        scanf("%s",s);
        int len=1;
        for(int i=1;i<n;++i)
            if(s[i]<s[i%len]) len=i+1;
            else if(s[i]>s[i%len]) break;
        int now=0;
        for(int i=1;i<=m;++i)
        {
            printf("%c",s[now]);
            ++now;
            if(now==len) now=0; 
        }
    }
    作者:xxy
    本文版权归作者和博客园共有,转载请用链接,请勿原文转载,Thanks♪(・ω・)ノ。
  • 相关阅读:
    JSP 隐含对象
    Cookie 和 Session
    Servlet(Server Applet) 详解
    AbstractQueuedSynchronizer 详解
    ThreadLocal 详解
    线程的生命周期
    phpfor函数和foreach函数
    php的while函数
    php的switch函数
    php的if函数
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/15366085.html
Copyright © 2020-2023  润新知