#1152 : Lucky Substrings
描述
A string s is LUCKY if and only if the number of different characters in s is a fibonacci number. Given a string consisting of only lower case letters, output all its lucky non-empty substrings in lexicographical order. Same substrings should be printed once.
输入
A string consisting no more than 100 lower case letters.
输出
Output the lucky substrings in lexicographical order, one per line. Same substrings should be printed once.
- 样例输入
-
aabcd
样例输出 -
a aa aab aabc ab abc b bc bcd c cd d
题目大意:给定一个只包含小写字母的字符串S。对于S的任意一个非空子串,若其包含的不同字母个数为fibonacci数列中的数,
则我们认为这个子串为幸运的。请找出S的所有幸运的子串。不要重复输出。解题思路
一个简单的解题思路是直接枚举S的所有子串,并对其不同字母个数进行统计。
S均由小写字母组成,因此其包含的不同字母个数最多为26个。而在26以内且属于fibonacci数列的数为1,2,3,5,8,13,21。因此只有当子串中不同字母的个数为1,2,3,5,8,13,21时,该子串才是幸运的。
接下来即是如何统计一个子串的不同字母个数,下面给出一种比较朴素的方法:
isLucky(subString):alphabet[] = falsecount = 0For c in subStringIf not alphabet[c] Thenalphabet[c] = truecount = count + 1End IfEnd ForReturn (count is Fibonaccid number)
S的最大长度为 N = 100,该朴素算法的时间复杂度为O(N^3),是可以通过所有数据的。
同时,我们可以通过一个小的优化,将算法的时间复杂度减少的O(N^2)。
在已经知道S[i..j]字母个数的情况下,我们可以直接推导出S[i..j+1]的不同字母个数。
首先我们需要改进
isLucky
函数:alphabet[] = false count = 0 isLucky(c):If not alphabet[c] Thenalphabet[c] = truecount = count + 1End IfReturn (count is Fibonaccid number)
这里我们把
alphabet
和count
从函数中抽取出来,作为了全局变量。同时,isLucky
的参数变为单个字符,每次将新增的S[j+1]加入统计中。下面是函数的主体部分:
For i = 0 .. len - 1alphabet[] = falsecount = 0For j = i .. len - 1// 此时isLucky返回的是S[i..j]的不同字母数量是否满足条件If isLucky(S[j]) ThenansList.push(S[i..j])End IfEnd For End For
最后只需要将
ansList
所保存的子串进行排序去重后输出,即可顺利通过该题目。1 #include
2 #include <string> 3 #include 4 #include 5 #include <set> 6 using namespace std; 7 string s; 8 9 bool IsFibonaccidNum(int n){ 10 return (n == 1 || n == 2 || n == 3 || n == 5 || n == 8 || n == 13 || n == 21); 11 } 12 13 bool isLucky(int i, int j){ 14 int alphabet[26] = { 0}; 15 //memset(alphabet, 0, sizeof(alphabet)); 16 int count = 0; 17 for(int k = i; k <= j; k++){ 18 if(alphabet[s[k] - 'a'] == 0){ 19 alphabet[s[k] - 'a'] = 1; 20 count++; 21 } 22 } 23 return (IsFibonaccidNum(count)); 24 } 25 26 int main(){ 27 set<string> set1; 28 cin >> s; 29 int len = s.length(); 30 for(int i = 0; i < len; i++){ 31 for(int j = i; j < len; j++){ 32 if(isLucky(i, j)){ 33 string str = s.substr(i, j - i + 1); 34 set1.insert(str); 35 } 36 } 37 } 38 39 for(set<string>::iterator it = set1.begin(); it != set1.end(); it++){ 40 cout << *it << endl; 41 } 42 //system("pause"); 43 return 0; 44 } 1 #include
2 #include <string> 3 #include 4 #include 5 #include <set> 6 using namespace std; 7 int alphabet[26] = { 0}, cnt; 8 9 bool IsFibonaccidNum(int n){ 10 return (n == 1 || n == 2 || n == 3 || n == 5 || n == 8 || n == 13 || n == 21); 11 } 12 13 bool isLucky(char c){ 14 if(alphabet[c - 'a'] == 0){ 15 alphabet[c - 'a'] = 1; 16 cnt++; 17 } 18 return (IsFibonaccidNum(cnt)); 19 } 20 21 int main(){ 22 set<string> set1; 23 string s; 24 cin >> s; 25 int len = s.length(); 26 for(int i = 0; i < len; i++){ 27 memset(alphabet, 0, sizeof(alphabet)); 28 cnt = 0; 29 for(int j = i; j < len; j++){ 30 if(isLucky(s[j])){ 31 string str = s.substr(i, j - i + 1); 32 set1.insert(str); 33 } 34 } 35 } 36 37 for(set<string>::iterator it = set1.begin(); it != set1.end(); it++){ 38 cout << *it << endl; 39 } 40 //system("pause"); 41 return 0; 42 }