【KMP】改变父串元素位置,最多组出多少子串 Codeforces Round #545 (Div. 2) D. Camp Schedule

 Codeforces Round #545 (Div. 2) D. Camp Schedule

http://codeforces.com/contest/1138/problem/D

给你父串和子串(都用01表示),问你改变父串的元素位置,使得子串在父串中出现次数最多,问你怎么做

上kmp的nxt数组得到子串前后缀相同最大长度

然后预处理出子串和父串0和1的个数

然后分类讨论

#include <bits/stdc++.h>
using namespace std;
const int maxn=5e5+10;
char s[maxn],t[maxn];
int nxt[maxn];

void getNxt(int m)
{
    int i=1,j=0;
    nxt[0]=0;
    while(i<m)
    {
        if(t[i]==t[j]) nxt[i++]=++j;
        else if(!j) i++;
        else j=nxt[j-1];
    }
}

int main()
{
    scanf("%s%s",s,t);
    int len1=strlen(s),len2=strlen(t);
    int len1_0=0,len1_1=0,len2_0=0,len2_1=0;
    for(int i=0; i<len1; i++)
    {
        int k=s[i]-'0';
        if(k==0) len1_0++;
        else len1_1++;
    }

    for(int i=0; i<len2; i++)
    {
        int k=t[i]-'0';
        if(k==0) len2_0++;
        else len2_1++;
    }

    getNxt(len2);
    int k=nxt[len2-1];

    if(len1<len2)
    {
        for(int i=0; i<len1; i++)
            cout<<s[i];
    }
    else if(len1==len2)
    {
        if(len1_0!=len2_0||len1_1!=len2_1)
        {
            for(int i=0; i<len1; i++)
                cout<<s[i];
        }
        else
        {
            for(int i=0; i<len1; i++)
                cout<<t[i];
        }
    }
//    10101000
//    101
    else
    {
        if(len2_0==0)
        {
            for(int i=1;i<=len1_1;i++)
            {
                cout<<"1";
            }
            for(int i=1;i<=len1_0;i++)
            {
                cout<<"0";
            }
            return 0;
        }
        else if(len2_1==0)
        {
            for(int i=1;i<=len1_1;i++)
            {
                cout<<"1";
            }
            for(int i=1;i<=len1_0;i++)
            {
                cout<<"0";
            }
            return 0;
        }

        if(len1_0<len2_0||len1_1<len2_1)
        {
            for(int i=0; i<len1; i++)
                cout<<s[i];
        }
        else
        {
            if(k==0)
            {
                int p=min(len1_0/len2_0,len1_1/len2_1);
                for(int j=1; j<=p; j++)
                {
                    for(int i=0; i<len2; i++)
                    {
                        cout<<t[i];
                    }
                }
                len1_0=len1_0-len2_0*p;
                len1_1=len1_1-len2_1*p;
                for(int i=1; i<=len1_0; i++)
                {
                    cout<<"0";
                }
                for(int i=1; i<=len1_1; i++)
                {
                    cout<<"1";
                }
            }
            else
            {
                int f0=0,f1=0;
                for(int i=k; i<len2; i++)
                {
                    int p=t[i]-'0';
                    if(p==0) f0++;
                    else f1++;
                }
                for(int i=0; i<len2; i++)
                {
                    cout<<t[i];
                }
                len1_0-=len2_0;
                len1_1-=len2_1;
                int p=min(len1_0/f0,len1_1/f1);

                len1_0=len1_0-f0*p;
                len1_1=len1_1-f1*p;
                for(int j=1; j<=p; j++)
                {
                    for(int i=k; i<len2; i++)
                    {
                        cout<<t[i];
                    }
                }
                for(int i=1; i<=len1_0; i++)
                {
                    cout<<"0";
                }
                for(int i=1; i<=len1_1; i++)
                {
                    cout<<"1";
                }
            }
        }
    }


    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值