Codeforces Round #545 (Div. 2) D. Camp Schedule(KMP next匹配)

32 篇文章 0 订阅
1 篇文章 0 订阅

D. Camp Schedule

今天!终于学会 K M P KMP KMP了!!

题意:给你 01 01 01 s s s, t t t,任意改变串 s s s的字符顺序,求构造一个字符串 c c c满足 t t t c c c中的出现次数最多。

题解:首先求出串 s s s 0 0 0 1 1 1数量,其次利用 K M P KMP KMP里的 n e x t next next数组,如果会 K M P KMP KMP的话,就知道,实际上 n e x t next next数组就是模式串的公共前缀后缀的最大长度表往右移了一格并将初始位置赋值为 − 1 -1 1。因此我们可以先构造一个串 t t t,然后去通过最长公共前缀后缀继续构造接下来的字符,最后再把剩余的 01 01 01加上去即可。这样就可以满足串 t t t的出现次数最多。比如 s = 101101 ,    t = 110 s = 101101,\;t= 110 s=101101,t=110,那么我们就可以先构造出 110 110 110,然后根据最长公共前缀和后缀为 0 0 0,那么接下来就需要模式串回溯到开头,然后添加 c = 110110 c = 110110 c=110110。因为是利用了已有的最长公共前缀和后缀,所以我们可以保证这样做是让 t t t出现次数最多的。

代码

#include<bits/stdc++.h>

#define DEBUG(x) std::cerr << #x << '=' << x << std::endl

using namespace std;
const int N = 5E5+10;
int nxt[N];
string s,t;

void getNext()
{
	int j = 0, k = -1, len = t.length();
	nxt[0] = -1;
	while(j < len) {
		if(k == -1 || t[j] == t[k]) {
			++j, ++k;
			if(t[j] != t[k]) {
				nxt[j] = k;
			}else{
				nxt[j] = nxt[k];
			}
		}else{
			k = nxt[k];
		}
	}
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
#endif
    ios::sync_with_stdio(false); cin.tie(0);
	cin >> s >> t;
	getNext();
	int one = 0, zero = 0;
	for(int i = 0; i < s.length(); ++i) {
		one += s[i] - '0';
		zero += !(s[i] - '0');
	}
	int it = 0;
	string ans = "";
	while(zero > 0 && one > 0) {
		if(t[it] == '0') {
			if(zero > 0) {
				zero--;
				ans += '0';
			}else{
				break;
			}
		}else{
			if(one > 0) {
				one--;
				ans += '1';
			}else{
				break;
			}
		}
		it++;
		if(it == t.length()) {
			it = nxt[it];
		}
	}
	for(int i = 0; i < zero; ++i) ans += '0';
	for(int i = 0; i < one; ++i) ans += '1';
	cout << ans << endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值