题目链接:
题目大意:
给出一个字符串A,再给出两个字符串B,C,求A中任意量字符交换后(不限制次数)能够得到的使B,C作为子串不重叠且出现次数最多的串
题目分析:
其实就是对A,B,C进行计数,判断A中的各个字母的个数分别能分给几个B和几个C,枚举B的个数,计算C的个数,然后取最大值即可,记录去最大值情况下B出现的次数和C出现的次数然后先把B,C输出对应次数,然后把剩下的字符输出出去就好了。比较恶心的是,这道题竟然卡常数,真的在卡常数,所以要进行一个小的剪枝,也就是先求出B出现的最大次数,也就是A全部转成B的情况下B的个数,优化效果出奇的好,但并不是证明优化效果,复杂度怎么算都是26*o(n)
代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define MAX 100007
int num1[50];
int num2[50];
int num3[50];
int num[50];
char s1[MAX];
char s2[MAX];
char s3[MAX];
using namespace std;
void scan ( char s[] )
{
char ch;
ch = getchar ();
int i = 0;
while ( true )
{
if ( ch == ' ' || ch == '\r' || ch == '\n' ) break;
s[i++] = ch;
ch = getchar();
}
s[i] = 0;
}
void print ( char s[] )
{
int i = 0;
while ( s[i] )
putchar ( s[i++] );
}
int main ( )
{
//while ( true )
//{
scan ( s1 );
memset ( num1 , 0 , sizeof ( num1 ) );
memset ( num2 , 0 , sizeof ( num2 ) );
memset ( num3 , 0 , sizeof ( num3 ) );
//scanf ( "%s" , s2 );
scan ( s2 );
//scanf ( "%s" , s3 );
scan ( s3 );
int len = strlen(s1);
for ( int i = 0 ; i < len ; i++ )
num1[s1[i]-97]++;
len = strlen(s2);
for ( int i = 0 ; i < len ; i++ )
num2[s2[i]-97]++;
len = strlen(s3);
for ( int i = 0 ; i < len ; i++ )
num3[s3[i]-97]++;
int ans = 0;
int sum1 = MAX , sum2 = MAX;
for ( int i = 0 ; i < 26 ; i++ )
if ( num2[i] )
sum1 = min ( sum1 , num1[i]/num2[i] );
for ( int i = 0 ; i < 26 ; i++ )
if ( num3[i] )
sum2 = min ( sum2 , num1[i]/num3[i] );
int index = sum1;
sum1 = sum2 = 0;
for ( int i = 0 ; i <= index ; i++ )
{
bool flag = false;
for ( int j = 0 ; j < 26 ; j++ )
{
num[j] = num1[j] - num2[j]*i;
if ( num[j] < 0 )
{
flag = true;
break;
}
}
if ( flag ) continue;
int temp = MAX;
for ( int j = 0 ; j < 26 ; j++ )
if ( num3[j] )
temp = min ( temp , num[j]/num3[j] );
if ( temp + i > ans )
{
ans = temp + i;
sum1 = i;
sum2 = temp;
}
}
if ( ans = 0 ) print(s1);
else
{
for ( int i = 0 ; i < sum1 ; i++ )
//printf ( "%s" , s2 );
print(s2);
for ( int i = 0 ; i < sum2 ; i++ )
//printf ( "%s" , s3 );
print(s3);
for ( int i = 0 ; i < 26 ; i++ )
num1[i] -= sum1*num2[i] + sum2*num3[i];
for ( int i = 0 ; i < 26 ; i++ )
while ( num1[i]-- )
//printf ( "%c" , 'a'+i );
putchar((char)('a'+i));
puts ("");
}
//}
}