【问题描述】
给你一串由小写字母组成的字符串, 希望你把它划分成一些小段,/span>中的字母都不相同, 并且希望分的段数尽量少。
然后, 把这些小段按字典序排序后输出, 中间由一个空格分隔。
例如: 字符串"nnsmpmn", 最少分成 3 小段: "n", "nsmp","mn"。
排序后输出:
mn n nsmp
注意, 有时候符合上面要求的方案可能有多个, 就要输出排序后字典序最小的那个。
例如: 字符串”aba”可以有 2 钟划分: a/ba 和 ab/a, 排序后分别是: ”a ba”和”a ab”。
应该输出:
a ab
【 输入格式】
(多组数据形式)
第 1 行: 一个不超过 10 的正整数 K, 表示有 K 组任务。
第 2~K 行, 每行一个由小写字母组成的字符串。 字符串长度范围为[1,50]。
【 输出格式】
按输入次序输出答案。
给你一串由小写字母组成的字符串, 希望你把它划分成一些小段,/span>中的字母都不相同, 并且希望分的段数尽量少。
然后, 把这些小段按字典序排序后输出, 中间由一个空格分隔。
例如: 字符串"nnsmpmn", 最少分成 3 小段: "n", "nsmp","mn"。
排序后输出:
mn n nsmp
注意, 有时候符合上面要求的方案可能有多个, 就要输出排序后字典序最小的那个。
例如: 字符串”aba”可以有 2 钟划分: a/ba 和 ab/a, 排序后分别是: ”a ba”和”a ab”。
应该输出:
a ab
【 输入格式】
(多组数据形式)
第 1 行: 一个不超过 10 的正整数 K, 表示有 K 组任务。
第 2~K 行, 每行一个由小写字母组成的字符串。 字符串长度范围为[1,50]。
【 输出格式】
按输入次序输出答案。
【 输入输出样例】
数据量不大,开始的时候觉得顺着搜一遍再倒着搜一遍就可以求出,发现不太对
正确的方法是DP。
p[i]表示的是第0-i个字母的最优解,用vector<string>来存,不难,自己能力问题
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define MAXN (50+5)
#define Set(a, v) memset(a, v, sizeof(a))
#define For(i, a, b) for(int i = a; i <= (int)b; i++)
#define Forr(i, a, b) for(int i = a; i >= b; i--)
#define pb push_back
string s;
char S[MAXN];
vector<string> p[MAXN], tmp;
int c[200];
int main(){
freopen("string.in", "r", stdin);
freopen("string.out", "w", stdout);
int T;
scanf("%d", &T);
while(T--){
cin>>s;
int slen = s.length()-1;
For(i, 0, slen) p[i].clear();
S[0] = s[0]; S[1] = '\0';
p[0].pb(string(S));
For(i, 1, slen){
Set(c, 0);
Forr(j, i, 0){
if(c[s[j]]++) break;
For(u, j, i) S[u-j] = s[u];
S[i-j+1] = '\0';
if(!p[i].size() || !j || p[i].size() > p[j-1].size()+1){
if(j) p[i] = p[j-1];
else p[i].clear();
p[i].pb(string(S));
sort(p[i].begin(), p[i].end());
}else if(p[i].size() == p[j-1].size()+1){
tmp = p[j-1];
tmp.pb(S);
sort(tmp.begin(), tmp.end());
For(k, 0, p[i].size()-1)
if(p[i][k] > tmp[k]){
p[i] = tmp;
break;
}else if(p[i][k] < tmp[k]) break;
}
}
}
cout<<p[slen][0];
For(j, 1, p[slen].size()-1) cout<<' '<<p[slen][j];
printf("\n");
}
return 0;
}