一个字符串,由前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 = + ;
const int P = (int)1e9 + ;
LL f[MAXN],g[MAXN];
char str[MAXN];
int pre[];
set<pii> rem;
LL solve(int n,int k){
int m = strlen(str + );
memset(pre,,sizeof(pre));
f[] = g[] = ;
for(int i=;i<=m;++i){
int v = str[i] - 'a';
if(pre[v] == )
f[i] = g[i - ];
else
f[i] = (g[i - ] - g[pre[v] - ] + P) % P;
g[i] = (g[i - ] + f[i]) % P;
pre[v] = i;
// printf("i = %d f = %lld g = %lld\n",i,f[i],g[i]);
}
rem.clear();
for(int i=;i<k;++i)
rem.insert(pii(pre[i],i));
for(int i=m+;i<=m+n;++i){
// puts("ffff");
pii now = *rem.begin();
int pos = now.fir,v = now.sec;
if(pos == )
f[i] = g[i - ];
else
f[i] = (g[i - ] - g[pos - ] + P) % P;
g[i] = (g[i - ] + 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\n",i,f[i]);
return g[m + n];
}
int main(){
int n,k;
scanf("%d %d",&n,&k);
scanf("%s",str + );
printf("%lld\n",solve(n,k));
return ;
}

codeforces 645 E. Intellectual Inquiry的更多相关文章

  1. Codeforces 645E. Intellectual Inquiry(DP,贪心)

    Codeforces 645E. Intellectual Inquiry 题意:给定一串字符,由前k个小写拉丁字母组成,要求在该字符串后面补上n个字符(也从前k个小写拉丁字母里面选),使得最后得到的 ...

  2. CROC 2016 - Elimination Round (Rated Unofficial Edition) E. Intellectual Inquiry 贪心 构造 dp

    E. Intellectual Inquiry 题目连接: http://www.codeforces.com/contest/655/problem/E Description After gett ...

  3. CROC 2016 - Elimination Round (Rated Unofficial Edition) E - Intellectual Inquiry dp

    E - Intellectual Inquiry 思路:我自己YY了一个算本质不同子序列的方法, 发现和网上都不一样. 我们从每个点出发向其后面第一个a, b, c, d ...连一条边,那么总的不同 ...

  4. codeforces 645E . Intellectual Inquiry

    题目链接 如果不考虑重复的元素, 那么我们可以很容易的发现, 长度为n的字符串它的子串数量是 $ 2^n $ . 我们设每个到位置i, 答案的数量为f[i]. 然后我们考虑重复的, 我们发现, 每加入 ...

  5. CF CROC 2016 Intellectual Inquiry

    题目链接:http://codeforces.com/contest/655/problem/E 大意是Bessie只会英文字母表中的前k种字母,现在有一个长度为m+n的字母序列,Bessie已经知道 ...

  6. codeforces 645 D. Robot Rapping Results Report 二分+拓扑排序

    题目链接 我们可以发现, 这是一个很明显的二分+拓扑排序.... 如何判断根据当前的点, 是否能构造出来一个唯一的拓扑序列呢. 如果有的点没有出现, 那么一定不满足. 如果在加进队列的时候, 同时加了 ...

  7. CodeForces - 645 C.Enduring Exodus

    快乐二分 用前缀和随便搞一下 #include <cstdio> using namespace std; ; int p[N]; ; inline int msum(int a, int ...

  8. 「CF645E」 Intellectual Inquiry

    题目链接 CF645E 题意 有一个长为\(n\)的由小写字母组成的字符串,需要用小写字母再填\(m\)位,使最后的字符串中本质不同的子串数量尽量多,答案对\(10^9+7\)取模. 本题数据:\(n ...

  9. 05.24 ICPC 2019-2020 North-Western Russia Regional Contest复现赛+Codeforces Round #645 (Div. 2)

    A.Accurate Movement(复现赛) 题意:两个木块最左边都在0的位置,最右边分别为a,b(b>a),并且短的木条只能在长木条内移动,问两个木条需要移动多少次才能使两个木条的右端都在 ...

随机推荐

  1. Java(一)

    这个学期要学习七章的东西,目前我对第一章的内容掌握的还算良好,我学会了布局管理器,菜单栏,面板等一些组件的使用,但是对于事件监听器的使用还是有所欠缺.另外对于其他六章的内容都一无所知,之前也没有浏览过 ...

  2. ARM指令教程

    ARM指令教程 ARM汇编程序特点: l         所有运算处理都是发生通用寄存器(一般是R0~R14)的之中.所有存储器空间(如C语言变量的本质就是一个存储器空间上的几个BYTE).的值的处理 ...

  3. 读取手机上所有应用程序并显示(APP)

    pd = ProgressDialog.show(getActivity(), "请稍候..", "正在收集软件信息...", true,false); Thr ...

  4. CentOS 6.5 升级 GCC 4.9.3

    1. GUN官网下载源代码安装包: gcc-4.9.3.tar.gz 2. 解压安装包,并进入解压后的文件夹: tar -zxvf gcc-4.9.3.tar.gz 3. 使用压缩包中的工具下载依赖: ...

  5. iphone 浏览器自动解析数字为号码解决方法

    iphone 浏览器自动解析数字为号码解决方法 www.MyException.Cn  网友分享于:2015-10-09  浏览:0次   iphone 浏览器自动解析数字为号码解决办法 在工作中遇到 ...

  6. 转载《android:scaleType属性》

    在网上查了好多资料,大致都雷同,大家都是互相抄袭的,看着很费劲,不好理解,自己总结一下,留着需要看的话来查找. 代码中的例子如下: <ImageView android:id="@+i ...

  7. 初步认知java的方法

    1.正确区分函数和方法: 面向对象的语言叫做方法,面向过程的语言叫做函数,两者的意义是一样的,只是叫法不同.java是面向对象的语言,所以用方法. 2.方法的定义: 就是有名字的代码段 3.方法的目的 ...

  8. #ifndef 的用法

    背景: 头件的中的#ifndef,这是一个很关键的东西.比如你有两个C文件,这两个C文件都include了同一个头文件.而编译时,这两个C文件要一同编译成一个可运行文件,会引起大量的声明冲突,这时候需 ...

  9. js模块化AMD/CMD

    JavaSript模块化 在了解AMD,CMD规范前,还是需要先来简单地了解下什么是模块化,模块化开发?     模块化是指在解决某一个复杂问题或者一系列的杂糅问题时,依照一种分类的思维把问题进行系统 ...

  10. memory corruption

    今天遇到了一个比较弱的问题,但是涉及到一些东西,所以记录一下. 问题表现为,系统BOSD,在析构函数进行free的时候,有的时候是在使用buffer的过程中就BSOD. 之前是怀疑因为分配的是page ...