一个很好的dp

Don’t Be a Subsequence
具体以后再补.没有想的很清楚
是这样..
首先,需要确定这个最短子串的长度,不是单纯的字典序最小,所以..就被他们想出来了个转移方程,dp[i]为[i….)这一段中最短的非子序列长度,那么此前的每一个,都是由后者可以转移而来,事实上,也就是枚举26个字母,最后返回来,走一遍来时的路,可能有多个满足条件的,取字典序最好的就行.

#include <iostream>
using namespace std;
#define debug(x) std::cerr << #x << " = " << (x) << std::endl
typedef long long LL;
const int MAXN = 2e5+17;
const int MOD = 1e9+7;
int dp[MAXN],nxt[MAXN][26+3],ocr[26+3];
int main(int argc ,char const *argv[])
{
    #ifdef noob
    freopen("Input.txt","r",stdin);freopen("Output.txt","w",stdout);
    #endif  
    string str;
    cin>>str;
    int n = str.length();
    for (int i = 0; i < 26; ++i)
    {
        ocr[i] = n;
    }
    for (int i = n-1; i > -1; --i)
    {
        ocr[str[i]-'a'] = i;
        for (int j = 0; j < 26; ++j)
        {
            nxt[i][j] = ocr[j];
        }
        dp[i] = MOD;
    }
    dp[n] = 1;
    for (int i = n-1; i > -1; --i)
        for (int j = 0; j < 26; ++j)
            dp[i] = min(dp[i],dp[nxt[i][j]+1]+1);
    for (int i = 0; dp[0]; --dp[0])
    {
        for (int j = 0; j < 26; ++j)
        {
            if(dp[i]==dp[nxt[i][j]+1]+1)
            {
                printf("%c",j+'a');
                i = nxt[i][j]+1;
                break;
            }
        }
    }
    return 0;   
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值