• CF1138D(545,div2) Camp Schedule


    https://vjudge.net/problem/CodeForces-1138D

    题目

    有两个字符串s和t,都只包括字符“0”和“1”,要求调整s中字符的顺序,最大化t作为字串出现的次数。

    $1 leqslant |s| leqslant 500\,000$,$1 leqslant |s| leqslant 500\,000$

    题解

    kmp模板题+贪心……

    kmp算法得到的是每个位置的最长公共前缀后缀,所以只需要使用整个字符串的最长公共前缀后缀就可以了

    先统计s中每个字符的个数,然后照着t贪心填充,如果没有把剩下的都输出,如果把t填充完了那么直接跳到前缀后面继续填充

    为什么出现次数最多?因为填充完毕一次以后,最少需要填充“整个字符串长度-前缀长度”个字符,填充其他的肯定没有这个更优

    时间复杂度O(n)

    AC代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<cctype>
    #include<cassert>
    #define REP(i,a,b) for(register int i=(a); i<(b); i++)
    #define REPE(i,a,b) for(register int i=(a); i<=(b); i++)
    #define PERE(i,a,b) for(register int i=(a); i>=(b); i--)
    using namespace std;
    typedef long long ll;
    #define MAXN 500007
    int f[MAXN];
    char s[MAXN], t[MAXN];
    inline void getf(char *s, int l) {
    	int t=f[0]=-1;
    	REP(i,0,l) {
    		while(t>=0 && s[i]!=s[t]) t=f[t];
    		t++; f[i+1]=t;
    	}
    }
    int main() {
    	scanf("%s%s", s, t);
    	int ls=strlen(s), lt=strlen(t);
    	int cnt[2]={0,0};
    	getf(t,lt);
    	REP(i,0,ls) cnt[s[i]-'0']++;
    	int pos=0;
    	while(1) {
    		if(cnt[t[pos]-'0']>0) {
    			putchar(t[pos]);
    			cnt[t[pos]-'0']--;
    			pos++;
    			if(pos==lt) pos=f[pos];
    		} else break;
    	}
    	while(0<cnt[0]--) putchar('0');
    	while(0<cnt[1]--) putchar('1');
    	putchar('
    ');
    
    }
    
  • 相关阅读:
    PHP AES256加密算法
    PHP字符串比较
    linux常用命令
    播放音乐方法(兼容IE FF Chrome Opera Safari)
    JS小游戏象棋暗棋
    Sublime Text 2 介紹
    php生成QRcode
    几种极其隐蔽的XSS注入的防护
    JS判断碰撞方法
    php 发送带附件邮件
  • 原文地址:https://www.cnblogs.com/sahdsg/p/12299013.html
Copyright © 2020-2023  润新知