Problem A. Lucky Substrings

Source

Problem

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

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

样例输出

  1. a
  2. aa
  3. aab
  4. aabc
  5. ab
  6. abc
  7. b
  8. bc
  9. bcd
  10. c
  11. cd
  12. d

题解

简单实现题,即判断 substring 中不同字符串的个数是否为 fibonacci 数,最后以字典序方式输出,且输出的字符串中相同的只输出一次。分析下来需要做如下几件事:

  1. 两重 for 循环取输入字符串的所有可能子串。
  2. 判断子串中不同字符的数目,这里使用可以去重的数据结构Set比较合适,最后输出Set的大小即为不同字符的数目。
  3. 判断不同字符数是否为 fibonacci 数,由于子串数目较多,故 fibonacci 应该首先生成,由于字符串输入最大长度为100,故使用哈希表这种查询时间复杂度为 $$O(1)$$ 的数据结构。
  4. 将符合条件的子串加入到最终结果,由于结果需要去重,故选用Set数据结构。

Java

  1. import java.util.*;
  2. public class Main {
  3. public static void main(String[] args) {
  4. Scanner in = new Scanner(System.in);
  5. String input = in.nextLine();
  6. Set<String> result = solve(input);
  7. for (String s : result) {
  8. System.out.println(s);
  9. }
  10. }
  11. public static Set<String> solve(String input) {
  12. Set<Long> fibonacci = fibonacci_number(input.length());
  13. Set<String> res = new TreeSet<String>();
  14. for (int i = 0; i < input.length(); i++) {
  15. for (int j = i + 1; j <= input.length(); j++) {
  16. String substr = input.substring(i, j);
  17. if (isFibonacci(substr, fibonacci)) {
  18. res.add(substr);
  19. }
  20. }
  21. }
  22. return res;
  23. }
  24. public static boolean isFibonacci(String s, Set<Long> fibo) {
  25. Set<Character> charSet = new HashSet<Character>();
  26. for (Character c : s.toCharArray()) {
  27. charSet.add(c);
  28. }
  29. // convert charSet.size() to long
  30. if (fibo.contains((long)charSet.size())) {
  31. return true;
  32. } else {
  33. return false;
  34. }
  35. }
  36. public static Set<Long> fibonacci_number(int n) {
  37. // generate fibonacci number till n
  38. Set<Long> fibonacci = new HashSet<Long>();
  39. long fn2 = 1, fn1 = 1, fn = 1;
  40. fibonacci.add(fn);
  41. for (int i = 3; i <= n; i++) {
  42. fn = fn1 + fn2;
  43. fibonacci.add(fn);
  44. fn2 = fn1;
  45. fn1 = fn;
  46. }
  47. return fibonacci;
  48. }
  49. }

源码分析

fibonacci 数组的生成使用迭代的方式,由于保存的是Long类型,故在判断子串 size 时需要将 size 转换为long. Java 中常用的 Set 有两种,无序的HashSet和有序的TreeSet.

复杂度分析

遍历所有可能子串,时间复杂度 O(n^2), fibonacci 数组和临时子串,空间复杂度 O(n).