ARC E - Don't Be a Subsequence DP

题目链接http://arc081.contest.atcoder.jp/tasks/arc081_c

题目大意:给你一个字符串,问不是这个字符串的最短字典序最小子序列是什么。如果一个字符串t是字符串s的子串,那么t可以由s通过删除0个或多个字符得到。

解题思路:我们先来确定字符串的长度,然后再通过长度的值递推出来子串。

如果t不是s的子序列,设字符c是t的第一个元素,那么

如果c在s中没有出现过,则t就是c

否则的话,设i是s中c第一次出现的位置,那么t.substr(2) 一定不是s.substr(i + 1)的子序列

因此我们设dp[i]为从第i(0 <= i <= s.length())个字符开始的不是s的子串的长度,那么有:

如果c('a' ~ 'z')在s中从第i + 1个位置开始未出现过,则dp[i] = 1

否则dp[i] = min(dp[nxt[i][j]] + 1)    0 <= j < 26,  nxt[i][j]指字符j在s中从第i+1个位置开始第一次出现的位置,初始值为-1

另一方面 nxt[i][j] = (str[i + 1] == 'a' + j)? i + 1: nxt[i + 1][j]

那么如果我们要找字典序最小的话:

如果dp[i] == 1, 则第一个满足nxt[i][c - 'a] == -1的字符c就是所求字符串末尾字符

否则的话当前字符应为满足dp[i] == dp[nxt[i][c - 'a']] + 1的第一个字符c, i = nxt[i][c - 'a']

代码:
 

char str[maxn]; 
int nxt[maxn][30], dp[maxn];

void solve(){
    memset(nxt, -1, sizeof(nxt));
    int len = strlen(str + 1);
    for(int i = len - 1; i >= 0; i--){
        for(int j = 0; j < 26; j++){
            nxt[i][j] = (str[i + 1] == 'a' + j)? i + 1: nxt[i + 1][j];
        }
    }
    memset(dp, 0x3f, sizeof(dp));
    for(int i = len; i >= 0; i--){
        bool flag = false;
        for(int j = 0; j < 26; j++){
            if(nxt[i][j] == -1){
                flag = true;
                dp[i] = 1;
                break;
            }
        }
        if(flag) continue;
        for(int j = 0; j < 26; j++){
            if(nxt[i][j] != -1)
                dp[i] = min(dp[i], dp[nxt[i][j]] + 1);
        }
    }
    for(int i = 0; i <= len; ){
        if(dp[i] == 1){
            for(int j = 0; j < 26; j++) {
                if(nxt[i][j] == -1){
                    printf("%c", j + 'a');
                    break;
                }
            }
            break;
        }
        for(int j = 0; j < 26; j++) {
            if(nxt[i][j] != -1 && dp[i] == dp[nxt[i][j]] + 1){
                printf("%c", j + 'a');
                i = nxt[i][j];
                break;
            }
        }
        
    }
    printf("\n");
}
int main(){
    scanf("%s", str + 1);
    solve();
}


题目:

E - Don't Be a Subsequence


Time limit : 2sec / Memory limit : 256MB

Score : 600 points

Problem Statement

A subsequence of a string S is a string that can be obtained by deleting zero or more characters from S without changing the order of the remaining characters. For example, arcartistic and (an empty string) are all subsequences of artisticabc and ci are not.

You are given a string A consisting of lowercase English letters. Find the shortest string among the strings consisting of lowercase English letters that are not subsequences of A. If there are more than one such string, find the lexicographically smallest one among them.

Constraints

  • 1≤|A|≤2×105
  • A consists of lowercase English letters.

Input

Input is given from Standard Input in the following format:

A

Output

Print the lexicographically smallest string among the shortest strings consisting of lowercase English letters that are not subsequences of A.


Sample Input 1

Copy

atcoderregularcontest

Sample Output 1

Copy

b

The string atcoderregularcontest contains a as a subsequence, but not b.


Sample Input 2

Copy

abcdefghijklmnopqrstuvwxyz

Sample Output 2

Copy

aa

Sample Input 3

Copy

frqnvhydscshfcgdemurlfrutcpzhopfotpifgepnqjxupnskapziurswqazdwnwbgdhyktfyhqqxpoidfhjdakoxraiedxskywuepzfniuyskxiyjpjlxuqnfgmnjcvtlpnclfkpervxmdbvrbrdn

Sample Output 3

Copy

aca

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值