牛客多校第七场 A String (01字符串最小表示法)
最开始看到这题的时候,从题目里给的样例就认为是把原串拆成n个最长的非递减序列,后来发现并不是这样,因为题目所要求的是将其拆分为最少的部分,并且所有部分都是满足在不同表示顺序中具有最小的字典序,和我的想法有那么些不同。
举个栗子:对于01101111这个串,按题目要求拆开所得的串就只有01101111,而按我自己的理解,就会拆成011和01111;这是两个的不同之处。
所以就只能按最大长度的最小表示法的方法做,上代码:
/*举个栗子:对于01101111这个串,按题目要求拆开所得的串
就只有01101111,而按我自己的理解,就会拆成011和01111;
这是两个的不同之处。
所以就只能按最大长度的最小表示法的方法做,上代码:*/
#include <bits/stdc++.h>
using namespace std;
const int maxn=2001;
int t;
string str;
bool judge(string s)
{
int i=0,j=1,k=0,ll=s.length();
while (i<ll && j<ll && k<ll)
{
int com=s[(i+k)%ll]-s[(j+k)%ll];
if(com==0)//两位相等的情况
k++;
else
{
if(com>0)//起点为i的轮回字符串比较大的时候
i+=(k+1);
else
j+=(k+1);//起点为j的轮回字符串比较大的时候
if(i==j)
j++;//避免相等的情况
k=0;
}
}
if(min(i,j)==0)
return 1;
else
return 0;
}//检测是否为最小表示
int main()
{
scanf("%d",&t);
while (t--)
{
cin>>str;
int len=str.length();
int l=0;
while(1)
{
for(int i=len; i>=0; i--) //枚举的i-l的长度,从大的开始枚举,因为要拆成最少部分,(i-l)即代表剩下的长度
{
string s=str.substr(l,i-l);//取子串的方式,前面时初始位置,后面时所取长度
if(judge(s))
{
cout<<s;
l=i;
break;
}
}
if(l!=len)
cout<<' ';
else
break;
}
cout<<endl;
}
return 0;
}
拼数https://www.luogu.org/problemnew/show/P1012
题意:给你N个数,求怎样让这n个数排在一起最大?
解答:我开始直接用string 的sort,因为可以直接实现字典序排序,但是我最后一个点没过,
输入
6
321 32 407 135 13 217
我的答案就不对,因为我的 先排321再排32,殊不知明显是32321比32132大。
正解很简单:我真的学到了,可以直接写一个cmp:return x+y>y+x; 这一点我觉得很难想到吧,我从来没这样写过。
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
#define ll long long
string a[25];
bool cmp(string x,string y)
{
return (x+y)>(y+x);
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
sort(a,a+n,cmp);
for(int i=0;i<n;i++)
cout<<a[i];
/*sort(a,a+n);
for(int i=n-1;i>=0;i--)
cout<<a[i];
cout<<endl;*/
return 0;
}
E. Subsequences (easy version)
http://codeforces.com/contest/1183/problem/E
不难看出子序列长度越大,代价越小,那么我们自然想到每次肯定是把长度大的先统计掉,这就有点像BFS时每次都处理同一个深度的节点。
然后我们就可以脑洞大开类比到BFS上去。以原始序列作为根节点,每个节点都指向其删除任意一个字符后所得到的子序列。按子序列长度扩展BFS,最后在搜索到第k个节点时输出答案就行了~
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=500010;
const ll INF=2147483647;
ll n,k,ans;
string a,cur,icur;
queue<string> q;
set<string> s;
int main()
{
cin>>n>>k;
cin>>a;
s.insert(a);
q.push(a);
while(!q.empty())
{
cur=q.front();
q.pop();
for(int i=0;i<cur.size();i++)
{
icur=cur;
icur.erase(i,1);//erase(pos,n); 删除从pos开始的n个字符,比如erase(0,1)就是删除第一个字符
if(s.size()<k&&!s.count(icur))//如果有k个点或者这个子序列出现过就不用再入队了。
{
s.insert(icur);
q.push(icur);
ans+=n-icur.size();//统计代价。
}
if(s.size()==k)
{
cout<<ans<<endl;
return 0;
}
}
}
if(s.size()<k)//没有k个子序列,无解。
{
cout<<"-1";
}
return 0;
}