前两天看到一道比较有意思的题,题目如下:
美丽字符串
先给几个定义:
1. 如果字符串s1可以通过删除s的某些字符而得到,则成s1可以由s生成
2. 如果s1比s2长,则称s1比s2更美丽;如果同样长,那么,如果strcmp(s1, s2) > 0,则称s1比s2更美丽
3. 如果s中每个字符都不相同,则称s是独特的
下面,给一个字符串s(所有字符都是小写英文字母),请求出:可以由 s 生成的最美独特字符串。
比如:输入:ababa,输出:ba
测试例:
输入:
nlhthgrfdnnlprjtecpdrthigjoqdejsfkasoctjijaoebqlrgaiakfsbljmpibkidjsrtkgrdnqsknbarpabgokbsrfhmeklrle
正确输出为:tsocrpkijgdqnbafhmle
建议大家先自己想一想再看下面的,这道题肯定有各种各样的好解法。
我是修改了原字符串的,得益于小写英文字母只有26个,时间和空间复杂度都是线性的。
BeautifulString函数每次找到针对当前字符串要生成的最美独特字符串的第一个字符,最多需26次即可得到最美独特字符串。
至于如何找到最美独特字符串的第一个字符也是比较容易的。只需从后往前遍历一遍字符串统计出每个字符后面有几种字符即可(不包含该字符本身),然后选出其后面的字符种类数最多的字符,如果后面的字符种类数最多的字符不止一个,则选出字符字典序最大的那个。
例如:abac,第一个a后面有bc两种字符(不包含a),第一个b后面ac两种字符,第一个c后面有0种字符,则从a、b中选出b为最美独特字符串的第一个字符。
然后就要对原字符串做一些处理了。遍历一遍字符串可以得到每个字符第一次出现的位置,删除选出的字符第一次出现位置之前的所有字符(因为他们对决定第二个字符是什么已经没用了),并且删除所有的选出的这个字符。
例如:上例中,选出b,则b之前的字符删掉,变为bac,再把所有的b删掉,变ac。
然后就可以把ac递归去选ac生成的最美独特字符串的第一个字符了,也就是原字符串生成的最美独特字符串的第二个字符。
最多递归26次可得到最美独特字符串。
1 #include <iostream> 2 using namespace std; 3 4 void BeautifulString(char* str, int len, char* btfStr, int indBtfStr) 5 { 6 if(str[0] == '\0') 7 return; 8 9 int sFstPos[26]; 10 int sHash[26]; 11 for(int i = 0; i < 26; ++i) 12 { 13 sFstPos[i] = -1; 14 sHash[i] = -1; 15 } 16 for(int i = 0; i < len; ++i) 17 { 18 int ind = str[i]-'a'; 19 if(sFstPos[ind] == -1) 20 sFstPos[ind] = i; 21 } 22 int num = 0; 23 for(int i = len-1; i >= 0; --i) 24 { 25 int ind = str[i]-'a'; 26 if(sHash[ind] == -1) 27 ++num; 28 sHash[ind] = num-1; 29 } 30 int max = 0; 31 char cur = 'a'; 32 for(int i = 0; i < 26; ++i) 33 { 34 if(sHash[i] >= max && (i+'a') >= cur) 35 { 36 max = sHash[i]; 37 cur = i+'a'; 38 } 39 } 40 cout<<cur; 41 btfStr[indBtfStr++] = cur; 42 btfStr[indBtfStr] = '\0'; 43 int indStr = 0; 44 for(int i = sFstPos[cur-'a']; str[i] != '\0'; ++i) 45 { 46 if(str[i] != cur) 47 str[indStr++] = str[i]; 48 } 49 str[indStr] = '\0'; 50 BeautifulString(str, indStr, btfStr, indBtfStr); 51 } 52 53 int main() 54 { 55 char str[200] = "nlhthgrfdnnlprjtecpdrthigjoqdejsfkasoctjijaoebqlrgaiakfsbljmpibkidjsrtkgrdnqsknbarpabgokbsrfhmeklrle\0"; 56 int len = 0; 57 while(str[len] != '\0') 58 ++len; 59 char btfStr[27] = "\0"; 60 BeautifulString(str, len, btfStr, 0); 61 getchar(); 62 63 return 0; 64 }