CodeForces 1137B Camp Schedule(KMP的next数组)

10 篇文章 0 订阅
10 篇文章 0 订阅

KMP的next数组, 参考:https://blog.csdn.net/weixin_42102584/article/details/88360361
题目意思:
给出两个0-1字符串s和t,问如何重排s可以使得产生的新字符串中包括最多的连续子串t,输出重排结果。
本题要点:
1、对字符串 t 计算 next 数组, next[lent] 就是字符串t的最长的前后缀, 假如 next[lent] == idx,
坐标范围 [1, idx] 这部分字符串假设是 x
坐标范围 [idx + 1, lent] 这部分字符串假设是 y,
xyyyyyy, 显然此种构造方式是最省字母的让 tt 多次出现的构造方式
2、用len0, len1 来统计字符串s中, ‘0’ 和 '1’出现的次数:
输出 调整后的 字符串 ans 时候,输出1, --len1, 输出0, --len0。
尽量每 lent 个字符,凑够 一个字符串 t。具体输出看代码。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int MaxN = 500010;
char s[MaxN], t[MaxN], ans[MaxN];
int Next[MaxN];
int lens, lent, len0, len1, len;

void calc_next()
{
	Next[1] = 0;
	for(int i = 2, j = 0; i <= lent; ++i)
	{
		while(j > 0 && t[i] != t[j + 1])
			j = Next[j];
		if(t[i] == t[j + 1])
			++j;
		Next[i] = j;
	}
}

void solve()
{
	len0 = 0, len1 = 0;
	for(int i = 1; i <= lens; ++i)
	{
		if(s[i] == '0')
			++len0;
		else
			++len1;
	}
	calc_next();
	len = lent - Next[lent];	//字符串 t的最长前后缀长度
	for(int i = 1, j = 1; i <= lens; ++i, ++j)
	{
		if(t[j] == '1' && len1)
		{
			ans[i] = '1';
			--len1;
		}else if(t[j] == '0' && len0){
			ans[i] = '0';
			--len0;
		}else{
			if(len1)
			{
				ans[i] = '1';
				--len1;
			}else{
				ans[i] = '0';
				--len0;
			}
		}
		if(j == lent)	
			j = Next[j];
	}
	printf("%s\n", ans + 1);
}

int main()
{
	scanf("%s%s", s + 1, t + 1);
	lens = strlen(s + 1), lent = strlen(t + 1);
	if(lens < lent)
	{
		printf("%s\n", s + 1);
		return 0;
	}
	solve();
	return 0;
}

/*
101101
110
*/

/*
110110
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值