字符串划分(DP+字符串处理)

来源:互联网 发布:联通网络客服电话 编辑:程序博客网 时间:2024/06/12 04:01
【问题描述】
给你一串由小写字母组成的字符串, 希望你把它划分成一些小段,/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_backstring 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;}



1 0