HDU 多校 Distinct Sub-palindromes 题解(打表or构造)

题目链接

题目大意

让你构造一个长为n的只包括小写字母的字符串,使得子字符串的回文串的个数最少(相同则算一个),求这样的字符串的个数

题目思路

打表

emm。。。。我根本想不到这种题目怎么写啊,对于这种题目,我以后还是直接打表就好了。。。但是打表的复杂度好高,只能跑出5组数组,但是看出第四组和第五组一样应该就知道什么了。不过这个打表难度有点大,可能是我太菜了qwq

构造

当n=1,2,3你会发现答案就是 2 6 n 26^{n} 26n
而如果是大于3,答案就是构造一个长度为3不同的循环节,来满足条件例如abcabcabcabc…,使得字串最多有3个不同的回文字串,你会发现其他的构造都比他大,所以答案就是262524

打表代码

注意要先给字符串s=一个串,不然后单个单个去修改s[i]这样的话,这样s.size()依然是0,使用substr函数的时候就会out_range

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define debug printf("I am here\n");
using namespace std;
typedef long long ll;
const int maxn=1e6+5,mod=998244353,inf=0x3f3f3f3f;
const double eps=1e-10;
int t,n,mi=inf,num[maxn];
string s;
bool check(int l,int r){
    while(l<=r){
        if(s[l++]!=s[r--]){
            return 0;
        }
    }
    return 1;
}
int cal(int n){
    int cnt=0;
    map<string,int> mp;//标记出现过的回文串
    for(int len=1;len<=n;len++){
        for(int j=0;j+len-1<n;j++){
            string temp=s.substr(j,len);
            if(check(j,j+len-1)&&!mp[temp]){
                mp[temp]=1;
                cnt++;
                if(cnt>mi){//优化暴力
                    return inf;
                }
            }
        }
    }
    return cnt;
}
void dfs(int pos,int len){
    if(pos==len){
        int zhi=cal(len);
        if(zhi<mi){
            num[zhi]=1;
            mi=zhi;
        }else if(zhi==mi){
            num[mi]++;
        }
        return ;
    }
    for(int i=1;i<=26;i++){
        s[pos]=i+'a'-1;
        dfs(pos+1,len);
    }
}
int main(){
    s="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    for(int len=1;len<=50;len++){
        mi=inf;
        dfs(0,len);
        printf("%d\n",num[mi]);
    }
    return 0;
}

ac代码

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define debug printf("I am here\n");
using namespace std;
typedef long long ll;
const int maxn=1e6+5,mod=998244353,inf=0x3f3f3f3f;
const double eps=1e-10;
int n,t;
int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        if(n==1){
            printf("26\n");
        }else if(n==2){
            printf("676\n");
        }else if(n==3){
            printf("17576\n");
        }else if(n>=4){
            printf("15600\n");
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值