codeforces 645 E. Intellectual Inquiry

一个字符串,由前k个字母组成,长度为m + n,其中前m个字符已经确定,后面n个由你自由选择,

使得这个串的不同的子序列的个数最多,空串也算一个子序列。

1 <= m <= 10^6,0 <= n <= 10^6,1 <= k <= 26

首先,我们考虑n = 0的情况,

问题就为给定一个字符串,求它有多少个不同的子序列。

pre[i]表示字母i最后出现的位置,初始化为0

f[i]表示以第i个字符结尾的与前面已经出现的子序列都不同的子序列个数

g[i] = ∑0<=j<=if[j]

则我们知道f[i] = ∑pre[i]<=j<=i-1f[j] 

则 if pre[i] == 0  then f[i] = g[i-1]

    if pre[i] > 0    then f[i] = g[i-1] - g[pre[str[i]]-1]

答案就是g[m]

那如果n > 0 呢?

从f的递推式我们知道,要使得f[i]最大,i处填的字符应该是pre值最小的i

那么我们接着遍历,每次拿pre最小的字符,更新f和pre值

最终答案就是g[n + m]

代码:

                                           
  //File Name: cf645E.cpp
  //Created Time: 2017年01月05日 星期四 13时53分24秒
                                   
#include <bits/stdc++.h>
#define LL long long
#define fir first
#define sec second
#define pii pair<int,int>
using namespace std;
const int MAXN = 2000000 + 2;
const int P = (int)1e9 + 7;
LL f[MAXN],g[MAXN];
char str[MAXN];
int pre[26];
set<pii> rem;
LL solve(int n,int k){
    int m = strlen(str + 1);
    memset(pre,0,sizeof(pre));
    f[0] = g[0] = 1;
    for(int i=1;i<=m;++i){
        int v = str[i] - 'a';
        if(pre[v] == 0)
            f[i] = g[i - 1];
        else
            f[i] = (g[i - 1] - g[pre[v] - 1] + P) % P;
        g[i] = (g[i - 1] + f[i]) % P;
        pre[v] = i;
//        printf("i = %d f = %lld g = %lld
",i,f[i],g[i]);
    }
    rem.clear();
    for(int i=0;i<k;++i)
        rem.insert(pii(pre[i],i));
    for(int i=m+1;i<=m+n;++i){
//        puts("ffff");
        pii now = *rem.begin();
        int pos = now.fir,v = now.sec;
        if(pos == 0)
            f[i] = g[i - 1];
        else
            f[i] = (g[i - 1] - g[pos - 1] + P) % P;
        g[i] = (g[i - 1] + f[i]) % P;
        pre[v] = i;
        rem.erase(rem.begin());
        rem.insert(pii(i,v));
    }
//    for(int i=0;i<=m+n;++i)
//        printf("i = %d f = %lld
",i,f[i]);
    return g[m + n];
}
int main(){
    int n,k;
    scanf("%d %d",&n,&k);
    scanf("%s",str + 1);
    printf("%lld
",solve(n,k));
    return 0;
}
原文地址:https://www.cnblogs.com/-maybe/p/6254128.html