hihoCoder week 84 P1 : Lucky Substrings 【dp】

本文探讨了如何判断一个字符串是否为幸运串,并按字典序输出所有幸运子串。通过两种方法实现:暴力枚举子串和利用动态规划预处理子串中不同字符的个数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

P1 : Lucky Substrings

Time Limit: 10000ms
Case Time Limit: 1000ms
Memory Limit: 256MB

Description

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.

Input

A string consisting no more than 100 lower case letters.

Output

Output the lucky substrings in lexicographical order, one per line. Same substrings should be printed once.

Sample Input
aabcd
Sample Output
a
aa
aab
aabc
ab
abc
b
bc
bcd
c
cd
d
定义一个串是lucky串:串中不同字符个数为斐波那契数。


题意:给你一个串,让你按字典序输出所有的lucky子串。


思路一:暴力枚举子串,直接统计。时间复杂度O(n^3)。

思路二:设置dp[i][j]表示str.(i, j)里面不同字符的个数。先预处理子串中不同字符个数(感觉麻烦的话直接用状压记录),然后枚举子串,时间复杂度O(n^2)。


思路一:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <string>
#define INF 1000000
#define eps 1e-8
#define MAXN (10000+10)
#define MAXM (2000000+10)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%.2lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while((a)--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
#define PI acos(-1.0)
#pragma comment(linker, "/STACK:102400000,102400000")
#define fi first
#define se second
using namespace std;
typedef pair<int, int> pii;
string G[MAXN];
string str, cstr;
map<char, bool> fp;
map<string, bool> tp;
int cnt;
bool judge(int s, int t)
{
    fp.clear(); int sum = 0;
    for(int i = s; i <= t; i++)
    {
        if(!fp[str[i]]) sum++;
        fp[str[i]] = true;
    }
    G[cnt] = str.substr(s, t-s+1);
    return sum == 1 || sum == 2 || sum == 3 || sum == 5 || sum == 8 || sum == 13 || sum == 21;
}
int main()
{
    while(cin >> str)
    {
        int len = str.size(); cnt = 0; tp.clear();
        for(int i = 0; i < len; i++)
            for(int j = i; j < len; j++)
                if(judge(i, j) && !tp[G[cnt]]) {tp[G[cnt]] = true; cnt++;}
        sort(G, G+cnt);
        for(int i = 0; i < cnt; i++) cout << G[i] << endl;
    }
    return 0;
}

思路二:


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <string>
#define INF 1000000
#define eps 1e-8
#define MAXN (10000+10)
#define MAXM (2000000+10)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%.2lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while((a)--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
#define PI acos(-1.0)
#pragma comment(linker, "/STACK:102400000,102400000")
#define fi first
#define se second
using namespace std;
typedef pair<int, int> pii;
string G[MAXN];
string str, cstr;
map<char, bool> fp;
map<string, bool> tp;
int cnt;
int dp[110][110];
bool State[1<<26];
bool judge(int sum){
    return sum == 1 || sum == 2 || sum == 3 || sum == 5 || sum == 8 || sum == 13 || sum == 21;
}
int main()
{
    while(cin >> str)
    {
        int len = str.size(); cnt = 0; tp.clear();
        for(int i = 0; i < len; i++)
        {
            for(int j = 0; j < 26; j++) State[1<<j] = false;
            for(int j = i; j < len; j++)
            {
                if(i == j) {dp[i][j] = 1; State[1<<(str[i]-'a')] = true;}
                else
                {
                    int val = str[j] - 'a';
                    dp[i][j] = dp[i][j-1] + (State[1<<val] ? 0 : 1);
                    State[1<<val] = true;
                }
            }
        }
        for(int i = 0; i < len; i++)
            for(int j = i; j < len; j++)
                if(judge(dp[i][j]) && !tp[str.substr(i, j-i+1)]) {G[cnt] = str.substr(i, j-i+1); tp[G[cnt]] = true; cnt++;}
        sort(G, G+cnt);
        for(int i = 0; i < cnt; i++) cout << G[i] << endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值