洛谷 P3989 [SHOI2013]阶乘字符串 解题报告

P3989 [SHOI2013]阶乘字符串

题目描述

给定一个由前\(n(\le 26)\)个小写字母组成的串\(S(|S|\le 450)\)。串\(S\)是阶乘字符串当且仅当前 \(n\) 个小写字母的全排列(共\(n!\)种)都作为的子序列(可以不连续)出现。

请判断出给定的串是否是阶乘字符串。


\(n> 21\)时无解,原因不明,留坑

剩下的状压一下就好了

\(dp_s\)表示集合\(s\)的所有排列出现的最前位置

枚举集合最后一个元素更新

\(yuu_{i,j}\)表示\(j\)\(i\)之后出现的最前位置


Code:

#include <cstdio>
#include <cstring>
int T,n,dp[1<<21],yuu[460][26];
char s[460];
int max(int x,int y){return x>y?x:y;}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%s",&n,s+1);
        if(n>21)
        {
            puts("NO");
            continue;
        }
        int len=strlen(s+1);
        for(int i=0;i<n;i++) yuu[len+1][i]=yuu[len][i]=len+1;
        for(int i=len-1;~i;i--)
        {
            for(int j=0;j<n;j++) yuu[i][j]=yuu[i+1][j];
            yuu[i][s[i+1]-'a']=i+1;
        }
        memset(dp,0,sizeof dp);
        for(int s=1;s<1<<n;s++)
            for(int i=0;i<n;i++)
                if(s>>i&1)
                    dp[s]=max(dp[s],yuu[dp[s^(1<<i)]][i]);
        puts(dp[(1<<n)-1]==len+1?"NO":"YES");
    }
    return 0;
}

2019.2.14

转载于:https://www.cnblogs.com/butterflydew/p/10372686.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值