其他分享
首页 > 其他分享> > L3-020 至多删三个字符 (30 分)

L3-020 至多删三个字符 (30 分)

作者:互联网

L3-020 至多删三个字符 (30 分)

给定一个全部由小写英文字母组成的字符串,允许你至多删掉其中 3 个字符,结果可能有多少种不同的字符串?

输入格式:

输入在一行中给出全部由小写英文字母组成的、长度在区间 [4, 10​6​​] 内的字符串。

输出格式:

在一行中输出至多删掉其中 3 个字符后不同字符串的个数。

输入样例:

ababcc

输出样例:

25

提示:

删掉 0 个字符得到 "ababcc"。

删掉 1 个字符得到 "babcc", "aabcc", "abbcc", "abacc" 和 "ababc"。

删掉 2 个字符得到 "abcc", "bbcc", "bacc", "babc", "aacc", "aabc", "abbc", "abac" 和 "abab"。

删掉 3 个字符得到 "abc", "bcc", "acc", "bbc", "bac", "bab", "aac", "aab", "abb" 和 "aba"。

分析:设f[i][j]表示前i个字符中删除j个不同字符串的数量(下标从1开始),根据第i个字符的状态,很容易想到第i个字符删或不删有两种情况,所以f[i][j]=f[i-1][j]+f[i-1][j-1]。但是仅仅这样考虑会把一些相同的字符串状态重复计算,比如 abcded,在计算f[6][2]时删去‘de’或者删去‘ed’都会得到‘abcd’,造成了重复计算,重复计算的数量为f[3][0],也就是前3个字符一个都不删的情况。在计算f[6][3]时重复计算的数量为f[3][1],也就是前3个字符删掉一个的情况。这时需要设置一个标记pos记录当前字符上一次出现的位置,如果pos>0&&j-(i-pos)>=0,则f[i][j]-=f[pos-1][j-(i-pos)],j-(i-pos)表示它到位置pos-1删除了几个字符。

#include <iostream>
#include <cstring>
using namespace std;
char str[1000000+10];
int f[1000000+10][4],hashTable[26];
int main(){
    scanf("%s",str+1);
    int n=strlen(str+1);
    for(int i=0;i<=n;i++) f[i][0]=1;
    for(int i=1;i<=n;i++){
        int pos=hashTable[str[i]-'a'];
        hashTable[str[i]-'a']=i;
        for(int j=1;j<=3;j++){
            f[i][j]=f[i-1][j-1]+f[i-1][j];
            if(pos&&j-(i-pos)>=0)
                f[i][j]-=f[pos-1][j-(i-pos)];
        }
    }
    printf("%d",f[n][0]+f[n][1]+f[n][2]+f[n][3]);
    return 0;
}

标签:至多,30,int,删掉,pos,L3,字符串,个字符,020
来源: https://blog.csdn.net/qq_40597059/article/details/102679170