题解:AT_abc225_f [ABC225F] String Cards
前言
发现其他所有题解都是 DP,实际上这题只需要一个贪心。
思路
假作法
老师看错难度把这题放到模拟赛的签到题,以至于我随意看了一眼后把字符串排了序后直接顺次输出。
发现过不了样例:
3 2
baa
ba
b
尝试解决
问题
问题出在哪?
最小字符串为
发现可能出现 aa ba。
解决方案
如何解决?
首先,无论我们选什么,
采用类似反悔贪心的思想,看能不能将
如果我们下一个字符串选了
于是对于
以上操作重复
新的问题已经出现~
交上去发现并不行,发现
真正做法
其实解决这个问题也很简单,无论是
时间复杂度
-
一找共
k 个字符串,时间复杂度为\mathcal{O}(k) 。 -
每轮一个排序找
S ,时间复杂度为\mathcal{O}(n\log{n}) 。 -
然后找
SA ,遍历找,逐字比较即可,更改也一个一个字符加即可,时间复杂度为\mathcal{O}(n\left|S\right|) 。
于是总的时间复杂度为
代码
代码很清晰,不写注释了,有问题评论区见。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
struct yc
{
string s;
bool bj;
}yy[5005];
string ans;
ll n,k,dd=1;
bool cmp(yc a,yc b){
return a.bj==b.bj?a.s<b.s:a.bj<b.bj;
}
void yb(){
sort(yy+1,yy+1+n,cmp);
ans+=yy[1].s;
ll dn=yy[1].s.size();
yy[1].bj=1;
ll i;
ll nn=n;
for(i=2;i<=n;i++){
if(yy[i].bj)break;
bool p=0;
for(ll j=0;j<dn;j++){
if(yy[i].s[j]!=yy[1].s[j]){
p=i;break;
}
}
if(p){
break;
}
string ns;
ns.clear();
ll id=yy[i].s.size();
for(ll j=dn;j<id;j++){
ns+=yy[i].s[j];
}
yy[i].s=(yy[i].s>(ns+yy[1].s))?ns+yy[1].s:yy[i].s;
}
n=nn;
}
int main(){
scanf("%lld%lld",&n,&k);
for(ll i=1;i<=n;i++){
cin>>yy[i].s;
}
while(k){
yb();
k--;
dd++;
}
cout<<ans<<endl;
return 0;
}