【codechef】Yet Another Problem On Strings (找最优解)

本文介绍了一种算法,用于从给定的包含小写字母的字符串中生成最大字典序的子串,并在多个可能的情况下选择最小的字典序子串。通过使用字符频率和ASCII值比较,该算法实现了字符串的有效排序和选择过程。

You are given a string X consisting of lowercase alphabets. You are required to generate the largest stringY from X by following the given instructions below:

  • frequency(Y[i]) in X >= frequency(Y[j]) in X, where 1<=j<=i-1 and frequency(c) in X denotes the the number of occurrences of the letter c in the string X.
  • ASCII(Y[i]) > ASCII(Y[j]), where 1<=j<=i-1.



If there are multiple such strings Y, then you are required to print the lexicographically smallest string among them.

Note: All strings are indexed from 1.

Input

  • The first line of the input contains an integer T denoting the number of test cases. The description of Ttest cases follows.
  • The first line of each test case contains a single string X

Output

  • For each test case, output a single line containing the string Y as described above.

Constraints

  • 1 ≤ T ≤ 1000
  • 1 ≤ Length of X ≤ 1000

Example

Input:
3
codejam
birlainstituteoftechnology
rrramu
Output:
acdejmo
abcfghlnot
amr

http://www.codechef.com/BTCJ2015/problems/BITCJ4

一道类似dp的题目,做法挺巧妙的。。

#include<iostream>
#include<algorithm>
#include<string>
#include<map>
#include<vector>
#include<cmath>
#include<queue>
#include<string.h>
#include<stdlib.h>
#include<stack>
#include<cstdio>
#define ll long long
using namespace std;
int main(){
	int t;
	cin>>t;
	while(t--){
		string x;
		cin>>x;
		int y[26]={0};
		int l[26];     //level
		int p[26];     //parent
		for(int i=0;i<26;++i){
			l[i]=1;
			p[i]=-1;
		}
		for(int i=0;i<x.length();++i){
			y[x[i]-'a']++;
		}
		int max=0,g=-1;
		for(int i=0;i<26;++i){
			for(int j=0;j<i;++j){
				if(y[i]>=y[j]&&l[i]<=l[j]&&y[i]>0&&y[j]>0){
					l[i]=l[j]+1;
					p[i]=j; 
				}
			}
			if(l[i]>max){
				max=l[i];
				g=i;
			}	
		}
		stack<int> sk; //因为要逆序数出 
		while(g!=-1){
			sk.push(g);
			g=p[g];
		}
		while(!sk.empty()){
			cout<<char(sk.top()+'a');
			sk.pop();
		}
		cout<<endl;
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值