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

D. Camp Schedule

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

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

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

发布了219 篇原创文章 · 获赞 23 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/Eternally831143/article/details/88412536
今日推荐