首页 > 试题广场 >

LUCKY STRING

[编程题]LUCKY STRING
  • 热度指数:12011 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
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.
示例1

输入

aabcd

输出

a 
aa 
aab 
aabc 
ab 
abc 
b 
bc 
bcd 
c 
cd 
d
#include<iostream>
#include<string>
#include <set>
using namespace std;
#define repeat(end) for(int _i=0;_i<end;_i++)
int fibo[]={1,1,2,3,5,8,13,21,34,55,89};
set<string> out;
int main()
{
	string str;
	cin>>str;
	repeat(str.size())
	{
		set<char> m;
		int f=1;
		for(int i=_i;i<str.size();i++)
		{
			m.insert(str[i]);
			if(m.size()==fibo[f])
			{
				out.insert(str.substr(_i,i-_i+1));
			}
			else if(m.size()==fibo[f+1]) 
				i--,f++;
		}
	}
	for(auto itor=out.begin();itor!=out.end();itor++)
	{
		cout<<*itor<<endl;
	}
	return 0;
}
由于字符串最多到26个,所以可以直接把fibonacci数组在本地求出来放进去。
利用set可以方便快速地对字符串去重,排序。由于每次 m.size()至多加一,所以判断fibonacci数的时候也可以从小到大进行比较。
发表于 2016-09-02 11:30:45 回复(1)
这个题目一开始想得太复杂了,其实,使用java来做,充分利用HashSet的唯一性和TreeSet的有序性,很容解决这个问题。但是,如果不使用这些集合,如何通过原生的算法来实现,确实还不是非常清楚,有思路的话可以一起交流下。以下是我的java的代码
import java.util.HashSet;
import java.util.Scanner;
import java.util.TreeSet;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        HashSet<Integer> fib = new HashSet<>();
        for (int i = 1, j = 0, t; i+j < 100;) {
            fib.add(i+j);
            t = i;
            i += j;
            j = t;
        }
        System.out.println(fib);
        while (sc.hasNext()) {
            String s = sc.nextLine();
            TreeSet<String> treeSet = new TreeSet<>();
            for (int i = 0; i < s.length(); i++) {
                for (int j = i + 1; j <= s.lengt敏感词reeSet.add(s.substring(i, j));
                }
            }

            for (String string : treeSet) {
                HashSet<Character> chs = new HashSet<>();
                for (int i = 0; i < string.length(); i++) {
                    chs.add(string.charAt(i));
                }
                if(fib.contains(chs.size()))
                    System.out.println(string);
            }
        }
    }
} 


发表于 2017-08-07 11:29:12 回复(2)
using System;
using System.Linq;
using System.Collections.Generic;
 
namespace LUCKYSTRING
{
    classMainClass
    {
        privatestaticList<int> dp = newList<int>();
        publicstaticvoidMain(string[] args)
        {
            string line;
 
            dp.Add(0);
            dp.Add(1);
            dp.Add(1);
            for(inti = 3; i <= 20; ++i)
            {
                dp.Add(dp[i - 1] + dp[i - 2]);
            }
            Dictionary < string, int> dic = newDictionary<string, int>();
            while(!string.IsNullOrEmpty(line = Console.ReadLine()))
            {
                dic.Clear();
                for(inti = 0; i < line.Length; ++i)
                {
                    for(intj = i; j < line.Length; ++j)
                    {
                        string temp = line.Substring(i, j - i + 1);
                        if(isLuckString(temp))
                        {
                            if(!dic.ContainsKey(temp))
                            {
                                dic.Add(temp, 1);
                            }
                        }
                    }
                }
                Dictionary<string, int> dicRet = dic.OrderBy(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
                foreach (KeyValuePair<string, int> item in dicRet)
                {
                    Console.WriteLine(item.Key);
                }
            }
        }
 
        privatestaticbool isLuckString(string str)
        {
            List<char> list = newList<char>();
            for(inti = 0; i < str.Length; ++i)
            {
                if(!list.Contains(str[i]))
                {
                    list.Add(str[i]);
                }
            }
            if(dp.Contains(list.Count))
            {
                returntrue;
            }
            else
            {
                returnfalse;
            }
        }
    }
}
运行时间O(n^2).
发表于 2016-11-09 17:02:00 回复(0)
//利用set去重,全局变量Fib根据需要动态添加元素,判断是否为fibonacci数.
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
vector<int> Fib;
bool isFib(int n){
	if(Fib.size()<2){
		Fib.push_back(1);
		Fib.push_back(2); 
	}
    while(n>Fib.back())
        Fib.push_back(Fib[Fib.size()-2]+Fib[Fib.size()-1]);
    if(find(Fib.begin(),Fib.end(),n)==Fib.end())
        return false;
    return true;
}
int count(string s){
    int p[26]={0},R=0;
    for(int i=0;i<s.length();i++)
        if(p[s[i]-'a']==0){
        	R++;
        	p[s[i]-'a']=1;
    	}
    return R;    
}
int main(){
    string str;
    set<string> s;
    cin>>str;
    int n=1;
    while(n<str.length()){
        for(int i=0;i<=str.length()-n;i++){
            string ss=str.substr(i,n);
            if(isFib(count(ss)))
                s.insert(ss);
        } 
		n++;     
    }
    set<string>::iterator it;
    for(it=s.begin();it!=s.end();it++)
        cout<<*it<<endl;
    return 0;
}

编辑于 2016-08-16 11:05:03 回复(4)
def islucky(ss):#判断是否是幸运数字
    if len(set(ss)) in Fibonacci:
        return True
    else:
        return False

def string(ss):#求所有子字符串
    results = []
    for x in range(len(s)):# x + 1 表示子字符串长度
        for i in range(len(s) - x):# i 表示偏移量
            results.append(s[i:i + x + 1])
    return results

s=input()
Fibonacci=[1,2,3,5,8,13,21]#26以内的feibonacci数(26个字母)
ans=list(set(string(s)))#set去重
ans.sort()#按字典序排序
for i in ans:
    if islucky(i):
        print(i)

发表于 2018-08-17 15:45:01 回复(0)

https://fanxinglanyu.blog.csdn.net/article/details/104621310

2.1 题意

判断当前字符串的所有子串不同字母的个数是否是斐波那契数,如果是,则输出,否则,继续判断下一个子串。

2.2 思路

  • 打表,打印100以内的斐波那契数
  • 用set<char>实现去重统计字符串个数,
  • 每次判断当前子串的不同字母的个数是否是斐波那契数,如果是,则存入set<string>(是想按字典序排序的要求);如果是下一个斐波那契数,重新判断,存入set<string>(是想按字典序排序的要求);如果不是,继续判断下一个子串。
  • 最后输出结果。

    3 参考代码

#include <cstring>
(803)#include <iostream>
#include <set>

using std::cin; using std::cout;
using std::set; using std::string;
using  std::endl;

int fib[] = {1,1,2,3,5,8,13,21,34,55,89};//打表
set<string> result;

int main()
{
    string str;
    cin >> str;
    int n = str.length();
    for(int i = 0; i < n; i++) {//遍历每个字符,确定子串的首字母
        set<char> s;//统计子串中的每个不同字符的数目
        int k = 1;
        for (int j = i; j < n; j++) {//固定首字母,增加剩余的字母
            s.insert(str[j]);
            if (s.size() == fib[k]) {//如果是斐波那契数,继续递增字母数量
                result.insert(str.substr(i, j - i + 1));//当前字符拼接从i开始长度为j-i+1的字符
            } else if (s.size() == fib[k + 1]) {//如果是下一个斐波那契数
                j--;//回头重新判断这个字符串(防止漏判)
                k++;//斐波那契数更新为下一个斐波那契数
            }
        }
    }

    for (auto it = result.begin(); it != result.end(); it++) {
        cout << *it << endl;
    }

    return 0;
}
发表于 2020-03-02 22:10:07 回复(0)
s = input()

def fib():
    a, b = 0, 1
    while b <= 100:
        a, b = b, a+b
        yield a

luckys = set()

for i in range(len(s)):
    for j in range(i+1, len(s)+1):
        sub = s[i: j]
        if len(set(sub)) in fib():
            luckys.add(sub)

luckys = list(luckys)
luckys.sort()
for lucky in luckys:
    print(lucky)


发表于 2019-08-06 02:21:26 回复(0)
#include <iostream>
#include <vector>
#include <string>
#include <set>
using namespace std;

class Solution
{
public:
    set<string> LuckyString(string in)
    {
        set<string>().swap(_res);
        for (int i = 0; i < in.length(); i++)
        {
            for (int j = 0; j + i <= in.length(); j++)
            {
                string sub = in.substr(i, j);
                set<char> tmp;
                for (int k = 0; k < sub.length(); k++)
                {
                    tmp.insert(sub[k]);
                }
                if (tmp.size() == 1 || tmp.size() == 2 || tmp.size() == 3 || tmp.size() == 5 || tmp.size() == 8 || tmp.size() == 13 || tmp.size() == 21)
                {
                    _res.insert(sub);
                }
            }
        }
        return _res;
    }
private:
    set<string> _res;
};

int main()
{
    string in;
    Solution s;
    while (cin >> in)
    {
        set<string> res = s.LuckyString(in);
        for (set<string>::iterator it = res.begin(); it != res.end(); it++)
        {
            cout << *it << endl;
        }
    }
    return 0;
}
发表于 2018-08-16 10:12:49 回复(0)
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <iostream>

using namespace std;

#define FOR(i, n) for(i = 0; i < n; i++)

//定义散列表链表结构
typedef struct node
{
    //node(const char* s) : str(s){}
    char str[101];
    struct node *next;
}*LstSubStr, LstSubStrNode;

//inline int getMaxFi(int);
//链表基本操作
inline void InitList(LstSubStr *L);
inline void InsertList(LstSubStr *L, string str);
inline int findSame(LstSubStr L, string str);
int cmp(const void *a, const void *b);
int cmp2(const void *a, const void *b);


int main()
{
    char s[101];
    int length, i, j, k, h, maxFiboLen, count = 0, index = 0, subIndex = 0, diffNum = 0;
    bool flag = false;
    cin.sync_with_stdio(false);
    cin >> s;
    length = strlen(s);


    string str(s);
    string curStr("");                //当前正在计算的str
    string currentStrs[101];        //已记录的组合
    LstSubStr longestSubStr[26];    //记录以每个字符为首的最长的Fibonacci串,是散列链表
    char SubStrs[8000][101];            //记录所有子串



    FOR(i, 26)
        InitList(&longestSubStr[i]);
    FOR(i, 26)                        //获得整个串中不同的字符个数
        if (str.find('a' + i) < str.size())
            count++;
    //maxFiboLen = getMaxFi(count);    //得到最长fibonacci长度

    //只要把
    FOR(i, length)                //遍历每个字符
    {
        k = 0;
//        flag = false;
        diffNum = 0;
        for (j = 0; i + j < length; j++)        //计算字符为并往后探索
        {
            //当前字符是否存在于当前字符串,不存在则附加到后面,存在则不用继续往后了
            //    cout << curStr.find(s[i + j]) <<" "<< curStr.size() << endl;
            if (curStr.find(s[i + j]) > curStr.size())
                diffNum++;
            curStr.append(&s[i + j], 1);
                
            switch (diffNum)
            {
            case 1:
            case 2:
            case 3:
            case 5:
            case 8:
            case 13:
            case 21:
            case 34:
            case 55:
            case 89:
                currentStrs[k++] = curStr;
            //    qsort(&currentStrs[k][0], (int)currentStrs[k].size(), sizeof(currentStrs[0][0]), cmp);
                break;
            default:
                break;
            }
            
            /*
            else if (curStr.size() == 1 && i + j < length)
            {
                curStr.append(&s[i + j], 1);
                currentStrs[k++] = curStr;
                maxFiboLen++;
                flag = true;
            }
            else
            {
                break;
            }*/
            
        }
        FOR(h, k)
        {
            index = currentStrs[h][0] - 'a';
            if (!findSame(longestSubStr[index], currentStrs[h]))
            {
            //    cout << currentStrs[h] << "\t\t" << currentStrs[h].size() << endl;
                strcpy(SubStrs[subIndex++], currentStrs[h].c_str());
                InsertList(&longestSubStr[index], currentStrs[h]);            //插入
            }
        }

/*
        if (flag)
            maxFiboLen--;*/

//        cout << endl;
//        cout << curStr << endl;

        //记录到最长串中
        //longestSubStr[i] = curStr;    //记录当前最长串
        curStr = "";        //清空当前串


    }
    qsort(SubStrs, subIndex, sizeof(SubStrs[0]), cmp2);
    FOR(i, subIndex)
        cout << SubStrs[i] << endl;



    return 0;
}


/*
inline int getMaxFi(int count)
{
    if (count >= 21)
    {
        return 21;
    }
    else if (count >= 13)
    {
        return 13;
    }
    else if (count >= 8)
    {
        return 8;
    }
    else if (count >= 5)
    {
        return 5;
    }
    else if (count >= 3)
    {
        return 3;
    }
    return count;
}*/

inline void InitList(LstSubStr *L)
{
    //LstSubStrNode s("");
    (*L) = (LstSubStrNode *)malloc(sizeof(LstSubStrNode));
    strcpy((*L)->str, "");
    
    //(*L) = &s;
    (*L)->next = NULL;
}
inline void InsertList(LstSubStr *L, string str)
{
//    LstSubStrNode s(str.c_str());
    LstSubStrNode *p;
    p = (LstSubStrNode *)malloc(sizeof(LstSubStrNode));
    strcpy(p->str, str.c_str());
    p->next = (*L)->next;
    (*L)->next = p;
}
inline int findSame(LstSubStr L, string str)    //找相同字符串,找到则返回1
{
    LstSubStrNode *p;
    string pstr;
    p = L;
    while (p->next != NULL)
    {
        p = p->next;
        pstr = p->str;
        if (str.size() == pstr.size() && pstr == str)
        {
            return 1;
        }
    }
    return 0;
}



int cmp(const void *a, const void *b)
{
    return *(char *)a - *(char *)b;
}
int cmp2(const void *a, const void *b)
{
    return strcmp((char *)a, (char *)b);
}
发表于 2018-04-23 09:30:07 回复(0)
#include <bits/stdc++.h>

using namespace std;

int fib[] = {1,1,2,3,5,8,13,21,34,55,89};
set<string> result;

int main()
{     string str;     cin>>str;     int n = str.length();     for(int i=0;i<n;i++)     {         set<char> s;         int k = 1;         for(int j=i;j<n;j++)         {             s.insert(str[j]);             if(s.size() == fib[k])                 result.insert(str.substr(i,j-i+1));             else if(s.size() == fib[k+1])                 j--,k++;         }     }     for(auto it=result.begin();it!=result.end();it++)         cout<<*it<<endl;     return 0;
}

发表于 2017-11-02 00:32:57 回复(0)
//常见做法,先求子串,然后判断字串字符个数是否属于菲波那切数,然后再去重放入容器,最后排序按字典输出。
#include<iostream>
#include<string>
#include<vector>
#include<string.h>
#include <algorithm>
using namespace std;
vector<string> str;
int count1 ,a[10] = {1,2,3,5,8,13,21,34,55,89};
void CF(string str2,int q){

    int e,r,count=0;
    int str3[100];
    for(e=0;e<q;e++){
        for(r=0;r<count;r++){
            if(str3[r] == str2[e]){
                break;
            }
        }
        if(r == count){
            str3[count] = str2[e];
            count++;
        }
    }
    for(e=0;e<10;e++){
        if(count == a[e]){
            break;
        }
    }

    if(e != 10){
		int t;
		for(t=0;t<count1;t++)
		{
			if( strcmp(str2.c_str(),str[t].c_str() ) == 0)
			{
				break;
			}
		}	
		if(t == count1){

			str.push_back(str2);
			count1++;
		}
    }
}
int main(){
    string str1,str2;
    while( cin >> str1 ){
		count1 = 0;
        int i,j,l = str1.length();
        for(i=0;i<l;i++){
            for(j=i;j<l;j++){
				str2 = str1.substr(i,j-i+1);
				CF(str2,str2.length());
            }
        }
		sort(str.begin(), str.end());
		for (i=0; i<count1; i++)
			cout << str[i]<< endl;
    }
    return 0;
}
//算法更新,利用set性质,统计字符串不同字符个数简化。
#include<iostream>
#include<string>
#include<set>//特殊性质可以自动排序(对字符串排序默认是按其字典序,切不重复录入!
using namespace std;
set<string> str;
int a[10] = {1,2,3,5,8,13,21,34,55,89};
int main(){
    string str1,str2;
    while( cin >> str1 ){
        int i,j,l = str1.length();
        for(i=0;i<l;i++){
            for(j=i;j<l;j++){
                int e,count = 0;
                str2 = str1.substr(i,j-i+1);
                for(e=97;e<=122;e++){//统计字符串中不同小写字母的个数,由于本题限定了输入的为小写字母 97到122 之间,故可用这种特殊方法。
        			if(str2.find(e) != string::npos)
            				count++;
                }
    			for(e=0;e<10;e++){
        			if(count == a[e])
            			break;
                }
    			if(e != 10)
        			str.insert(str2);
            }
        }
        for(auto it = str.begin();it!=str.end();it++)//auto 型,可以在声明变量时根据变量的初始值,自动进行类型匹配。
            cout<<*it<<endl;   
    }
    return 0;
}

编辑于 2017-06-24 12:29:18 回复(0)

LUCKY STRING

思路

  1. 构造100以内的fibonacci数。
  2. 取substring,判断是否是fibonacci数,可以用set保存substring的不同字符。

代码

public static void main(String[] args) {
        // 输入
        Scanner in = new Scanner(System.in);
        String s = in.next();

        // 构造fibonacci数set
        // 输入字符串不多于100,所以只需要构造100以内
        Set<Integer> fib = new HashSet<>();
        int a = 1;
        int b = 1;
        for (int i = 1; i <= 20; i++) {
            if (b > 100) break;
            fib.add(b);
            int sum = a + b;
            a = b;
            b = sum;
        }

        // 用来保存子串中的字符,set的size代表不同字符的个数
        Set<Character> temp = new HashSet<>();
        // treeSet用来排序结果
        Set<String> res = new TreeSet<>();
        for (int i = 0; i < s.length(); i++) {
            temp.add(s.charAt(i));
            for (int j = i; j < s.length(); j++) {
                if (j > i) temp.add(s.charAt(j));
                // 检查该数子是否是fibonacci数
                if (fib.contains(temp.size())) res.add(s.substring(i, j + 1));
            }
            temp.clear();
        }

        // 输出
        for (String s1 : res) {
            System.out.println(s1);
        }
    }
发表于 2017-05-20 22:33:28 回复(0)
import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        String s = new Scanner(System.in).next();
        int a = 1, b = 1;
        HashSet<Integer> set = new HashSet<>();
        HashSet<String> list = new HashSet<>();
        for (int i = 3; i <= 50; i++) {
            set.add(b);
            int c = a + b;
            a = b;
            b = c;
        }
        HashSet<Character> dup = new HashSet<>();
        for (int i = 0; i < s.length(); i++) {
            dup.add(s.charAt(i));
            for (int j = i; j < s.length(); j++) {
                if (j > i)
                    dup.add(s.charAt(j));
                if (set.contains(dup.size()))
                    list.add(s.substring(i, j + 1));
            }
            dup.clear();
        }

        String[] ss = list.toArray(new String[]{});
        Arrays.sort(ss);
        for (String s1 : ss) {
            System.out.println(s1);
        }
    }
}

发表于 2017-04-24 20:56:22 回复(0)
// 抓住几个要点即可:
// 1. 寻找子字符串; 2.子字符串的不同字符个数;3.判断是不是fibnacci数
#include<bits/stdc++.h>
using namespace std;
int countDif(string s) {
    unordered_map<char, int> umap;
    for (auto item : s) {
        umap[item]++;
    }
    return static_cast<int>(umap.size());
}

bool isFib(int num) {
    int pre = 0;
    int cur = 1;
    int next = 0;
    while (next < num) {
        next = pre + cur;
        pre = cur;
        cur = next;
    }
    return num == next;
}

int main() {
    string s;
    cin >> s;
    unordered_map<string, int> si;
    vector<string> res;
    for (size_t i = 0; i < s.size(); ++i) {
        for (size_t j = i; j < s.size(); ++j) {
            string subs = s.substr(i, j-i+1);
            if (isFib(countDif(subs))) {
                if (si[subs]++ == 0)
                    res.push_back(subs);
            }
        }
    }
    sort(res.begin(), res.end());
    for (auto item : res)
        cout << item << endl;
    return 0;
}

发表于 2016-11-16 20:29:39 回复(1)
import java.util.*;
 
public class Main {
    public static void main(String[] args) {
        //得到一个26以内的fibonacci的数组
        int[] fib= getFib(26);
        ArrayList<String> luckys = new ArrayList<>();//保存lucky子串
        
        Scanner in = new Scanner(System.in);
        String str = in.next();
        
        //获取所有不重复的子串
        Set<String> allSubStr= new HashSet<>();
        for(int i=0;i<str.length();i++){
            for(int j= i;j<str.length();j++){
                allSubStr.add(str.substring(i,j+1));
            }
        }
        
        //字典排序所有子串
        ArrayList<String> subList=new ArrayList<>();
        subList.addAll(allSubStr);
        Collections.sort(subList);
        
        //统计每个子串的不同字符数
        for(String item:subList){
            int[] flag = new int[26];
            int characters=0;
            for(int i=0;i<item.length();i++){
                flag[item.charAt(i)-'a'] = 1;
            }
            //统计flag中1的个数
            for(int j=0;j<26;j++){
                if(flag[j]==1) characters++;
            }
            
            //如果characters在fib数组中,那么这个item是lucky子串 ,输出,同时保存
            if(contains(fib,characters)){
                luckys.add(item);
                System.out.println(item);
            }
        }
        
        
    }
    
    
    //返回一个fibonacci数组 n是数组大小
    public static int[] getFib(int n){
        int[] res= new int[n];
        res[0]=1;
        res[1]=1;
 
        if(n==1||n==2) return res;
        int i= 2;
        while(i++<n-1){
            res[i] = res[i-1]+res[i-2];
        }
        return res;
    }
    
    //检查数组是否包含目标值
    public static boolean contains(int[] src,int target){
        for(int i:src){
            if(i == target) return true;
        }
        return false;
    }
}
根据前人的提示完成,供参考。

发表于 2016-07-21 15:34:20 回复(1)
//毫无疑问,必须穷举!
//然后问题的关键就是求一个字符串中不同元素的个数:
//    1,利用unique算法,把重复元素分离,计算剩余元素个数
//    2,利用在较小字符串的基础上,分析新加入字符的重复性,加1或者加0,类似动态规划
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
void fill_fib(vector<int> &fib){
	int f1=1,f2=1;
	fib[1]=fib[2]=1;
	int f=0;
	while(f<=26){
		f=f1+f2;
		fib[f]=1;//f is fibonacci number,then fib[f]=1;
		f1=f2;
		f2=f;
	}
}
void work_out(string str,int **c,vector<string> &cands,vector<int> &fib){
	int n=str.size();
	for(int i=0;i<n;++i){
		c[i][i]=1;
		cands.push_back(string(str,i,1));
	}
	for(int l=2;l<=n;++l){
		for(int i=0;i<n+1-l;++i){
			int j=i+l-1;
			string::iterator p=find(str.begin()+i,str.begin()+j,str[j]);
			if(p==str.begin()+j)
				c[i][j]=c[i][j-1]+1;
			else
				c[i][j]=c[i][j-1];
			if(fib[c[i][j]]==1)
				cands.push_back(string(str.begin()+i,str.begin()+j+1));
		}
	}
}	
int main(){
	string str;
	cin>>str;
	int n=str.size();
	vector<int> fib(26,0);
	fill_fib(fib);
	vector<string> cands;
	int **c=new int*[n];
	for(int i=0;i<n;++i)
		c[i]=new int[n];
	work_out(str,c,cands,fib);
	sort(cands.begin(),cands.end());
	vector<string>::iterator u=unique(cands.begin(),cands.end());
	for(vector<string>::iterator ite=cands.begin();ite!=u;++ite)
		cout<<*ite<<endl;
	return 0;
}


发表于 2016-07-21 10:29:31 回复(0)
因为不同的小写字母只有26个,所以首先求0-26之间的斐波那契数,然后开始扫描字符串,扫描一次,每次扫描从起始位置一直找到终点,在过程中设置数组a[26]记录每个字符访问的次数,difnum表示从起始位置到当前位置中不同字符的个数,如果当前字符从未访问过,则difnum加1,如果difnum是斐波那契数,则将起始位置到当前位置的字符串存储起来,最后对所有的字符串直接用冒泡排序即满足字典顺序,并注意删去重复元素。

#include <iostream>
#include <string>
#include <vector>
using namespace std;
bool findNum(inta[],intnumber);
intfibonacci(int*a);
intmain()
{
inta[26]={0};
vector<string> subString;
intn=fibonacci(a); //求0-26之间的斐波那契数
string s;
//cout<<"请输入string s:";
cin>>s;
intpos=0;
for(inti=0;i<s.size();i++)
{
intj=i;
intletter[26]={0}; //记录字母访问的次数
intdif=0;  //表示当前串中不同字符的个数
while(j<s.size())
{
pos=s[j]-97; //97='a'
if(letter[pos]==0)//首次放入,证明从i到j-1构成一个dif长度的字符串
{
dif++;
if(findNum(a,dif))//如果斐波那契中存在这个数
{
subString.push_back(s.substr(i,j+1-i));//s.substr(pos,length)
}
}
elseif(findNum(a,dif))//如果斐波那契中存在这个数
subString.push_back(s.substr(i,j+1-i));
letter[pos]++; //放置
j++;
}
}
for(inti=0;i<subString.size();i++)//冒泡排序,并除去重复的元素
for(intj=0;j<subString.size()-i-1;j++)
{
if(subString[j]>subString[j+1])
{
//string temp=subString[j];
//subString[j]=subString[j+1];
//subString[j+1]=temp;
//subString.swap(subString.begin()+j,subString.begin()+j+1);
swap(subString[j],subString[j+1]);
}
elseif(subString[j]==subString[j+1])
subString.erase(subString.begin()+j,subString.begin()+j+1);
}
for(inti=0;i<subString.size();i++)
cout<<subString[i]<<endl;
return0;
}
intfibonacci(int*a)
{
a[0]=0;
a[1]=1;
inti=2;
while(i<26)
{
a[i]=a[i-2]+a[i-1];
if(a[i]>26)
{
a[i]=0;
break;
}
elsei++;
}
returni;//返回斐波那契数的个数
}
bool findNum(inta[],intnumber)
{
for(inti=0;i<26;i++)
{
if(a[i]==number)
returntrue;
}
returnfalse;
}
编辑于 2016-04-15 16:33:36 回复(0)
这道题其实是对数据结构的考察:set,sort等
发表于 2017-01-01 12:27:49 回复(0)
import java.util.*;

public class Test {
	public static void main(String[] args) {
		Scanner sc=new Scanner(System.in);
		String str=sc.next();
		sc.close();
		//首先计算斐波那契数字,不多于100位意味着100之内的斐波那契数就行
		Set<Integer> fib=new HashSet<Integer>();
		for (int i = 1; i < 20; i++) {
			fib.add(fibonacci(i));
		}
		//拆分字符串
		Set<String> subStr=new HashSet<String>();
		for (int i = 0; i < str.length(); i++) {
			for (int j = i; j < str.length(); j++) {
				subStr.add(str.substring(i, j+1));
			}
		}
		//对子字符串集合进行排序
		ArrayList<String> strList=new ArrayList<String>();
		strList.addAll(subStr);
		Collections.sort(strList);
		//比对并输出
		Set<Character> chs=new HashSet<Character>();
		for (String s : strList) {
			char[] ch=s.toCharArray();
			for (char c : ch) {
				chs.add(c);
			}
			if (fib.contains(chs.size())) {
				System.out.println(s);
			}
			chs.clear();
		}
	}
	public static int fibonacci(int n){
		if (n==1||n==2) {
			return 1;
		}
		else {
			return fibonacci(n-1)+fibonacci(n-2);
		}
	}
}


发表于 2015-11-16 13:46:00 回复(13)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>

//26个字母,数列最大21
int f[] = {1,2,3,5,8,13,21};

//判断个数
bool islucky(char *buf){
    int hash[26] = {0};
    int n = 0;
    for(int i = 0; i < strlen(buf); i++){
        if(hash[buf[i]-'a'] == 0){
            n++;
            hash[buf[i]-'a']++;
        }
    }
    for(int i = 0; i < 7; i++){
        if(n == f[i]) return true;
    }
    return false;
}

//字典序排序
int cmp(const void *a,  const void *b){
    return strcmp(*(char**)a, *(char**)b);
}

int main()
{
    char s[10000];
    scanf("%s", s);
    int n = strlen(s);
    char **ans  = malloc(sizeof(char *) * 10001);
    for(int i = 0; i < 10001; i++){
        ans[i] = malloc(sizeof(char) * n + 1);
    }
    int index = 0;
    char buf[n+1];
        //列出所有子序列
    for(int i = 0; i < n; i++){
        int top = 0;
        for(int j = i; j < n; j++){
            buf[top++] = s[j];
            buf[top] = '\0';
            strcpy(ans[index++], buf);
        }
    }
    qsort(ans, index, sizeof(char*), cmp);

        //只输出符合条件的子序列
    printf("%s\n",ans[0]);
    for(int i = 1; i < index; i++){
        if(islucky(ans[i]) && strcmp(ans[i], ans[i-1]) != 0)
            printf("%s\n",ans[i]);
    }
}

发表于 2021-07-15 11:17:57 回复(0)