【枚举】【最小表示法】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem F. Matrix Game
给你一个n*m的字符矩阵,将横向(或纵向)全部裂开,然后以任意顺序首尾相接,然后再从中间任意位置切开,问你能构成的字典序最大的字符串。
以横向切开为例,纵向类似。
将所有横排从大到小排序,枚举最后切开的位置在哪一横排,将这一排提到排序后的字符串数组最前面,求个“最大表示法”,如果最大表示法的位置恰好在第一排的位置,那么可以用来更新答案。
如果不在第一排的位置,那么其所构成的仍然是合法的串,而且一定不会影响答案。
这是一个最小表示法的板子。
#include<cstdio>
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
string a[105],ans,b[105];
int n,m;
bool cmp(const string &a,const string &b){
return a>b;
}
int MaxRep(string s, int l)
{
int i,j,k;
i=0;j=1;k=0;
while(i<l&&j<l)
{
k=0;
while(s[i+k]==s[j+k]&&k<l) k++;
if(k==l) return i;
if(s[i+k]<s[j+k]) //¸Ä³É´óÓÚ¾ÍÊÇ×îС±íʾ
if(i+k+1>j) i=i+k+1;
else i=j+1;
else if(j+k+1>i) j=j+k+1;
else j=i+1;
}
if(i<l) return i;
else return j;
}
int main(){
// freopen("f.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=0;i<n;++i){
cin>>a[i];
}
for(int i=0;i<n;++i){
for(int j=0;j<m;++j){
b[j]+=a[i][j];
}
}
sort(a,a+n,cmp);
for(int i=0;i<n;++i){
string t=a[i];
for(int j=0;j<n;++j){
if(j!=i){
t+=a[j];
}
}
// cout<<i<<": "<<t<<' ';
int p=MaxRep(t,n*m);
string pre=t.substr(0,p);
t.erase(0,p);
t+=pre;
// cout<<t<<endl;
ans=max(ans,t);
}
sort(b,b+m,cmp);
for(int i=0;i<m;++i){
string t=b[i];
for(int j=0;j<m;++j){
if(j!=i){
t+=b[j];
}
}
// cout<<i<<": "<<t<<' ';
int p=MaxRep(t,n*m);
string pre=t.substr(0,p);
t.erase(0,p);
t+=pre;
// cout<<t<<endl;
ans=max(ans,t);
}
for(int i=0;i<n*m;++i){
if(i!='0'){
for(int j=i;j<n*m;++j){
putchar(ans[j]);
}
puts("");
return 0;
}
}
return 0;
}
——The Solution By AutSky_JadeK From UESTC
转载请注明出处:http://www.cnblogs.com/autsky-jadek/

浙公网安备 33010602011771号
