CSU-ACM2017暑假集训比赛2 E - ( ̄▽ ̄)/
2017-08-02 21:22
399 查看
E - ( ̄▽ ̄)/
You are given a string s, consisting of lowercase English letters, and the integer m. One should choose some symbols from the given string so that any contiguous subsegment of length m has at least one selected symbol. Note that here we choose positions of symbols, not the symbols themselves. Then one uses the chosen symbols to form a new string. All symbols from the chosen position should be used, but we are allowed to rearrange them in any order. Formally, we choose a subsequence of indices 1 ≤ i1 < i2 < ... < it ≤ |s|. The selected sequence must meet the following condition: for every j such that 1 ≤ j ≤ |s| - m + 1, there must be at least one selected index that belongs to the segment [j, j + m - 1], i.e. there should exist a k from 1 to t, such that j ≤ ik ≤ j + m - 1. Then we take any permutation p of the selected indices and form a new string sip1sip2... sipt. Find the lexicographically smallest string, that can be obtained using this procedure.
Input
The first line of the input contains a single integer m (1 ≤ m ≤ 100 000). The second line contains the string s consisting of lowercase English letters. It is guaranteed that this string is non-empty and its length doesn't exceed 100 000. It is also guaranteed that the number m doesn't exceed the length of the string s.
Output
Print the single line containing the lexicographically smallest string, that can be obtained using the procedure described above.
Example
Input 3 cbabc Output a Input 2 abcab Output aab Input 3 bcabcbaccba Output aaabb
Note
In the first sample, one can choose the subsequence {3} and form a string "a". In the second sample, one can choose the subsequence {1, 2, 4} (symbols on this positions are 'a', 'b' and 'a') and rearrange the chosen symbols to form a string "aab".
题目描述很复杂,看了许久才看明白啥意思。
为方便表达,将两个字母中字典顺序靠前的称为“较小的字母”,反之称为“较大的字母”。
要求在原字符串中确定若干个位置,这些位置上的字符满足:从字符串中以每一个字符为起点,取出的若干个长度为 m 的子串中都包含它们,并且这些字符升序排列组成的字符串是所有可能结果中字典序最小的。
条件中“字典序最小”很重要。以输入样例3为例,有“aabb”和“aaabb”两种取法,前者长度较短,看上去更优,但后者字典序更小。所以必须仔细考虑算法方案。
经过思考可以知道,要使字典序最小,就需要在更大的字母存在时尽量多地加入更小的字母置于结果字符串的前部。而在更大字母数量一样时,较小字母全部加入结果前部自然能令结果字典序最小。所以总结出以下贪心方法:
扫描原字符串时,对每一个长度为 m 的小区间都找到小区间中最小的字母,以区间为单位记录遇到这个字母的次数,再将区间起点设置为这个最小字母的后一位;接着,在后面这个区间中找到最小的字母。若后面这个最小字母还大于前面的最小字母,则认为比后面这个最小字母还要小的字母被全部选中,对遇到字母次数的统计重置,将下一区间的起点设置为后发现的这个“较大的最小字母”的后一位。以此类推。
最终,只需要将比我们遇到的最大字母小的字母按升序输出,每个字母在原字符串中有几个就输出几个;然后输出遇到的最大字母,遇到几次输出几次,即得结果。
#include <iostream> #include <cstdio> #include <algorithm> #include <vector> #include <map> #include <cstring> using namespace std; char status[27], sample[100004]; map<char,int> stat; //用一个map存储每个字母出现的次数 int main(){ #ifdef TEST freopen("test.txt", "r", stdin); #endif // TEST status[1] = 'a'; for(int i = 2; i <= 26; i++)//用来为map的重置提供坐标 status[i] = status[i-1]+1; int m; while(cin >> m){ for(int i = 1; i<= 26; i++) stat[status[i]] = 0; scanf("%s", sample); int len = strlen(sample), sc = 1, last = 0; for(int i = 0; i < len; i++){ stat[sample[i]]++; } for(int i = 0; i < len-m+1;){ int Pos = i; char tempC = sample[i]; for(int j = i+1; j < i+m; j++){ if(sample[j] <= tempC){ Pos = j; tempC = sample[j]; } } while(status[sc]<sample[Pos])sc++, last = 0;//sc用于保存当前所需的最大字母,last记录最大字母需要多少个。 if(sample[Pos]==status[sc])last++; i = Pos+1; } for(int i = 1; i < sc; i++)//原字符串中有几个就输出几个 for(int j = 0; j < stat[status[i]]; j++) putchar(status[i]); for(int i = 0; i < last; i++)//遇到的最大字母,遇到几次就输出几个 putchar(status[sc]); cout << endl; } return 0; }
相关文章推荐
- CSU-ACM2017暑假集训比赛1 TD POJ3111
- CSU-ACM2017暑假集训比赛2 D - ^(●゚∀゚○)ノ
- CSU-ACM2017暑假集训比赛7 C - Pasha and Tea - CodeForces - 557B
- CSU-ACM2017暑假集训比赛1 B - R2D2 and Droid Army
- CSU-ACM2017暑假集训比赛2 B - : )
- CSU-ACM2017暑假集训比赛7 - D - Bicoloring - UVA - 10004
- CSU-ACM2017暑假集训比赛8 - E - Escape - HDU - 3605
- CSU-ACM2017暑假集训比赛2 A - _(:з」∠)_
- CSU-ACM2017暑假集训比赛1 A - I Can Guess the Data Structure! -uva111995
- CSU-ACM2017暑假集训比赛7 - E - Courses - HDU - 1083
- CSU-ACM2017暑假集训比赛2 CodeForces - 724D
- CSU-ACM2017暑假集训比赛1 C - Gourmet and Banquet CodeForces - 589F
- CSU-ACM2017暑假集训比赛8 - A - Xor Sum - HDU - 4825
- CSU-ACM2017暑假集训比赛1 C - Gourmet and Banquet
- CSU-ACM2017暑假集训比赛7 - F - 凑数字 - 51Nod - 1385
- CSU-ACM2017暑假集训比赛1 C - Gourmet and Banquet
- CSU-ACM2017暑假集训比赛8 - B - The Two Routes - CodeForces - 601A
- CSU-ACM2017暑假集训比赛2 HDU - 1597 find the nth digit
- CSU-ACM2017暑假集训比赛2 C - (╯°口°)╯(┴—┴
- CSU-ACM2017暑假集训比赛8 - C - GCD Table - CodeForces - 582A