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

【问题描述】
给你一串由小写字母组成的字符串, 希望你把它划分成一些小段,/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来存,不难,自己能力问题

#include
#include
#include
#include
#include
#include
#include

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 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<



你可能感兴趣的:(其他------DP__,字符串------)