题意:给一个字符串,让你每次从头和尾选一个字符到新字符串,使得最后选得的字符串在字典序最小。注意输出格式,每80个换行,除非最后一个已经是换行否则不换行
思路:这题据说是用后缀数组写的,等我学到了再做一遍~我看到的第一个思路就是枚举同时包含点贪心的思想。
枚举即按照顺序一个个选字符进新字符串
贪心即肯定选择两边最小的字母,因为按照字典序的话是成立的。
枚举中要处理的一些细节,例如CCBDCC和CCBCC,即头和尾相等的话,比较头+1和尾-1的大小,如果还是相等再执行一样的步骤,只到你知道选头还是尾
如果是对称的字符串那随便选左和右都行。
#include<iostream>
#include<string>
using namespace std;
char old[30005],ans[30005];
int main()
{
int i,n,ll,rr;
cin>>n;
for(i=0;i<n;i++)
cin>>old[i];
int l=0,r=n-1,num=0;
while(r>=0&&l<=n-1)
{
if(l==r) { ans[num]=old[l];break;} //如果剩下一个,选上就行
if(old[l]<old[r])
{
ans[num]=old[l];
l=l+1;
}
else if(old[l]>old[r])
{
ans[num]=old[r];
r=r-1;
}
else if(old[l]==old[r])
{
ll=l+1;rr=r-1; //如果头尾相等,比较头+1和尾-1的大小
while(1)
{
if(ll==rr) //如果ll都等于rr了,说明是对称形式的字符串,选左边即可
{
ans[num]=old[l];
l=l+1;
break;
}
if(old[ll]<old[rr])
{
ans[num]=old[l];
l=l+1;
break;
}
else if(old[ll]>old[rr])
{
ans[num]=old[r];
r=r-1;
break;
}
else {ll=ll+1;rr=rr-1;} //如果头和尾还是相等,继续往内比较
}
}
num++; //记得num++
}
for(i=0;i<n;i++)
{
cout<<ans[i];
if(i%80==79) cout<<endl; //记得80个换行
}
if(i%80!=0) cout<<endl; //如果之前换过行了就不再换行
}
}