CF1137B. Camp Schedule(KMP)

题目链接:https://vjudge.net/contest/361017#problem/F
http://codeforces.com/problemset/problem/1137/B
在这里插入图片描述在这里插入图片描述在这里插入图片描述
题意:在一个母字符串a中,尽可能地拼出拼出最多要求的字符串b,同时母字符串可以重新排序,b在a中可以重叠一部分但不可以完全重叠。
如 10101中可以看成2个101
解题思路:
直接利用KMP来找字符串匹配,注意这里我是去找len-1的位置的最大前缀后缀(重叠时必须要求后缀从最后一位就有重叠,且这样可以最大化的利用重叠,节省01来给后面的拼凑),然后先在a中放置一个b,之后直接利用len-1地方的最大前缀后缀的那一个点进行后序添加就可以。
注意点:
注意字符串b中1的个数为0或者0的个数为0的情况(除数不可以为0)

#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
#define maxs 500050
int Next[maxs];
int mark[maxs];
string s;
string t;
int s0,s1;
int t0,t1;
int m0,m1;
int lens,lent;
void get_next()
{
	Next[0]=-1;
 	for (int i=1;i<lent;i++){
    int j=Next[i-1];
    while ((t[j+1]!=t[i])&&(j>-1))
        j=Next[j];
    if (t[j+1]==t[i])
        Next[i]=j+1;
     else
		 Next[i]=-1;
    }
}
int main()
{
	cin>>s;
	cin>>t;
	lens=s.size();
	for(int i=0;i<lens;i++)
	{
		if(s[i]=='0')
			s0++;
		else
			s1++;
	}
	lent=t.size();
	for(int i=0;i<lent;i++)
	{
		if(t[i]=='0')
			t0++;
		else
			t1++;
	}
	get_next();
	int last=Next[lent-1];
	for(int i=0;i<=last;i++)
	{
		if(t[i]=='0')
			m0++;
		else
			m1++;
	}
	m0=t0-m0;
	m1=t1-m1;
	if(s0<t0||s1<t1)
	{
		for(int i=0;i<s0;i++)
			printf("0");
		for(int i=0;i<s1;i++)
			printf("1");
		cout<<endl;
	}
	else if(m0||m1)
	{
		s0-=t0;
		s1-=t1;
		cout<<t;
		int p;
		if(m0!=0&&m1!=0)
			p=min(s0/m0,s1/m1);
		else if(m0==0&&m1!=0)
			p=s1/m1;
		else if(m0!=0&&m1==0)
			p=s0/m0;
		s0-=p*m0;
		s1-=p*m1;
		string temp=t.substr(last+1,lent-last-1);
		for(int i=0;i<p;i++)
			cout<<temp;
		for(int i=0;i<s0;i++)
			printf("0");
		for(int i=0;i<s1;i++)
			printf("1");
		cout<<endl;
	}
	else
	{
		int p=maxs;
		if(t0!=0)
			p=min(p,s0/t0);
		if(t1!=0)
			p=min(p,s1/t1);
		s0-=p*t0;
		s1-=p*t1;
		for(int i=0;i<p;i++)
			cout<<t;
		for(int i=0;i<s0;i++)
			printf("0");
		for(int i=0;i<s1;i++)
			printf("1");
		cout<<endl;
	}
	return 0;
}
原创文章 65 获赞 3 访问量 2113

猜你喜欢

转载自blog.csdn.net/littlegoldgold/article/details/104813496
今日推荐