codeforces1137B kmp(fail的妙用)

摘要:
它是前缀和后缀的同一部分。然后我们认为$kmp$算法中的$fail$函数是为了找到这个东西。然后我们首先使t字符串失败一次以获得$next$数组,然后使前缀出现一次,然后使除前缀之外的后缀尽可能多地出现,这样答案字符串必须最大,最后输出剩余的01。请记住,用于扫描字符串的for循环决不能用作条件,否则它是一个$n2$算法。

题目传送门

题意:给出$s$和$t$两个串,让你构造出一个答案串,使得答案串中的01数量和s一样,并且使$t$在答案串中作为子串出现次数最多。

思路:

  要想出现的次数尽可能多,那么就要重复的利用,哪一部分是可以重复利用的呢?就是前缀和后缀相同的部分,然后我们就想到了$kmp$算法中$fail$函数就是求这个东西的,那么我们先对t串fail一遍得到$next$数组,然后先使前缀出现一次,然后就使除了前缀以外的后缀尽可能出现的多,这样得到的答案串必定是最多的,最后把剩余的01输出就可以了。

  记住扫描字符串的for循环千万不要用(i<strlen(s))当条件,否则就是个$n2$的算法了(你会tle15)。

codeforces1137B kmp(fail的妙用)第1张codeforces1137B kmp(fail的妙用)第2张
#include<bits/stdc++.h>
#define clr(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=500010;
int n,f[maxn],a,b;
char s[maxn],p[maxn];
void fail(){
    f[0]=-1;
    for(int j=1;j<n;j++)
    {
        for(int i=f[j-1];;i=f[i])
        {
            if(p[j]==p[i+1]){
                f[j]=i+1;
                break;
            }else if(i==-1)
            {
                f[j]=-1;
                break;
            }
        }
    }
    for(int i=0;i<n;i++)f[i]++;
}
int main(){
    while(scanf("%s",s)!=EOF)
    {
        scanf("%s",p);
        n=strlen(p);
        fail();
        a=b=0;
        int si=strlen(s);
        for(int i=0;i<si;i++)
        {
            if(s[i]=='0')a++;
            else b++;
        }
        int xx=0,yy=0;
        for(int i=0;i<f[n-1];i++)
        {
            if(p[i]=='0')xx++;
            else yy++;
        
        }
        if(a>=xx&&b>=yy)
        {
            for(int i=0;i<f[n-1];i++)printf("%c",p[i]);
            a-=xx,b-=yy;
            int xxx=0,yyy=0;
            for(int i=f[n-1];i<n;i++)
            {
                if(p[i]=='0')xxx++;
                else yyy++;
            }
            int flag=0;
            while(a>0&&b>0)
            {
                if(a<xxx||b<yyy)break;
                for(int i=f[n-1];i<n;i++)
                {
                    printf("%c",p[i]);
                }
                a-=xxx,b-=yyy;
            }
            while(a>0){
                printf("0");
                a--;
            }
            while(b>0){
                printf("1");
                b--;
            }
            puts("");
        }else{
            printf("%s
",s);
        }
    }
}
View Code

免责声明:文章转载自《codeforces1137B kmp(fail的妙用)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇云时代架构读后感四通达OA 11.5 SQL注入漏洞复现下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

JRebel 6 破解版及使用方法

2.解压下载的jrebel6.0.0-crack.zip、jrebel6.0 jar包和破解文件。假设文件在D:/jrebel步骤:1中解压缩。eclipse下载jrebe插件,可以在市场上下载。2.打开eclipse的窗口首选项jrebel,打开优势选项卡,并将jar包的路径指向D:/jrebel/jrebel.jar。用CMD打开DOS窗口,输入cd/d...

数据可视化之powerBI技巧(十四)采悟:PowerBI中自制中文单位万和亿

最令人不快的事情之一是数据单元的设置。现在让我们看看如何通过设置测量值来切换单位。需要动态选择1万元和1亿元的单位进行显示。首先,手动创建单位表,然后使用单位表中的[unit]字段生成切片器。下一步是建立销售衡量标准。销售额=总和('订单'[销售额])为了按过滤单位显示销售额,SELECTEDVALUE函数可以根据切片器选择动态更改分母。如果切片器未进行任何...

dBFs和dBm

dBFs和dBmdBFs是用来表征数字域功率值的大小,一般情况下我们定义0dBFs为数字域满刻度功率值,即数字域中功率的最大值;因此看到的dBFs的值都是负的。...

koroFileHeader插件快速入门使用教程

插件下载插件可以直接在vscode的扩展中查找koroFileHeader,但是有时候由于网络的问题会查找不到软件。插件配置koroFileHeader支持许多功能,但是不是所有功能都是需要,我们关注往往是如何配置注释内容和注释的一些选项。"fileheader.cursorMode":{//这部分是函数头的配置},"fileheader.customMad...

解决curl: (35) OpenSSL SSL_connect: Connection reset by peer in connection to raw.githubusercontent.com:443 错误

报告命令curl-o时出错-https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh| bash错误状态的原因是未安装git。使用以下命令安装git,然后执行上面的命令sudoapt-geinstallgit-referencehttps://www.pianshen.com/articl...

删除隐藏网卡(本机IP地址被占用)4个方法

关闭注册表,重新启动windowsxp或重新登录,在设备管理器中单击查看->显示隐藏设备,展开“网络适配器”卸载原来的老网卡,在重设IP就不会显示IP地址被占用了。方法2:要删除系统中隐藏的网卡,我们必须运行regedit打开注册表编辑器,找到HKEY_LOCAL_MCHINE\SYSTEM\CurrentControlSetControl\Network\...