Description

给定一个长度为$n$的字符串,串中的字符保证是前$k$个小写字母。你可以在字符串后再添加$m$个字符,使得新字符串所包含的不同的子序列数量尽量多。当然,前提是只能添加前$k$个小写字母。求新的长度为$n+m$的串最多的不同子序列数量。答案对$10^9+7$取模。

Input

输入第一行两个数$m,k$。
接下来一行一个字符串,长度为$n$,表示原始的字符串$s$。

Output

一个数,表示答案。

Sample Input

1 3
ac

Sample Output

8

HINT

$n,m\;\leq\;10^6,k\;\leq\;26$

Solution

当$m=0$时,

$lst[i]$表示字符$i$上一次出现的位置,

$f[i]$表示以第$i$位结尾的新出现的不同的子序列的个数.

以第$x(lst[i]\;\leq\;x<i)$位结尾的新出现的子序列末尾加上$s[i]$为一个新的子序列.(反证法可证$x(0<x<lst[i])$不可行)

$f[i]=\sum_{j=lst[s[i]]}^{i-1}f[j]$.

这个可以用前缀和优化.

当$m\not=0$时,

设$sum[i]=\sum_{j=1}^{i}f[j]$,

则$f[i]=sum[i-1]-sum[lst[j]-1](n<i\;\leq\;n+m)$

$f[i]$最大,即$lst[j]-1$最小.

  1. #include<cmath>
  2. #include<ctime>
  3. #include<queue>
  4. #include<stack>
  5. #include<cstdio>
  6. #include<vector>
  7. #include<cstring>
  8. #include<cstdlib>
  9. #include<iostream>
  10. #include<algorithm>
  11. #define K 2000005
  12. #define M 1000000007
  13. using namespace std;
  14. int s[K],sum,tmp,m,n,t;
  15. bool u[K];char c;
  16. int f[K],lst[K];
  17. inline void Aireen(){
  18. scanf("%d%d",&m,&t);
  19. c=getchar();
  20. for(n=1;scanf("%c",&c)==1;++n){
  21. if(!(c>='a'&&c<='z'))
  22. break;
  23. if(lst[c-'a'])
  24. f[n]=(s[n-1]-s[lst[c-'a']-1]+M)%M;
  25. else f[n]=(s[n-1]+1)%M;
  26. s[n]=(s[n-1]+f[n])%M;
  27. lst[c-'a']=n;
  28. }
  29. --n;
  30. if(t) for(int i=n+1,j,k;i<=n+m;++i){
  31. k=lst[0];j=0;
  32. for(int l=1;l<t;++l){
  33. if(lst[l]<k){
  34. k=lst[l];j=l;
  35. }
  36. }
  37. printf("j=%d\n",j);
  38. if(lst[j])
  39. f[i]=(s[i-1]-s[lst[j]-1]+M)%M;
  40. else f[i]=(s[i-1]+1)%M;
  41. s[i]=(s[i-1]+f[i])%M;
  42. lst[j]=i;
  43. }
  44. printf("%d\n",(s[n+m]+1)%M);
  45. }
  46. int main(){
  47. freopen("string.in","r",stdin);
  48. freopen("string.out","w",stdout);
  49. Aireen();
  50. fclose(stdin);
  51. fclose(stdout);
  52. return 0;
  53. }

因为卡空间$1MB$,每次转移只与$f[lst[i]-1]$有关,所以只需$O(k)$的空间.

  1. #include<cmath>
  2. #include<ctime>
  3. #include<queue>
  4. #include<stack>
  5. #include<cstdio>
  6. #include<vector>
  7. #include<cstring>
  8. #include<cstdlib>
  9. #include<iostream>
  10. #include<algorithm>
  11. #define K 26
  12. #define M 1000000007
  13. using namespace std;
  14. int s[K],lst[K],sum,tmp,m,n,t;
  15. char c;
  16. inline void Aireen(){
  17. scanf("%d%d",&m,&t);
  18. c=getchar();
  19. for(n=1;scanf("%c",&c)==1;++n){
  20. if(!(c>='a'&&c<='z'))
  21. break;
  22. tmp=s[c-'a'];s[c-'a']=sum;
  23. if(lst[c-'a']) sum=((sum<<1)%M-tmp+M)%M;
  24. else sum=((sum<<1)+1)%M;
  25. lst[c-'a']=n;
  26. }
  27. --n;
  28. if(t) for(int i=1,j,k;i<=m;++i){
  29. k=lst[0];j=0;
  30. for(int l=1;l<t;++l){
  31. if(lst[l]<k){
  32. k=lst[l];j=l;
  33. }
  34. }
  35. tmp=s[j];s[j]=sum;
  36. if(lst[j]) sum=((sum<<1)%M-tmp+M)%M;
  37. else sum=((sum<<1)+1)%M;
  38. lst[j]=i+m;
  39. }
  40. printf("%d\n",(sum+1)%M);
  41. }
  42. int main(){
  43. freopen("string.in","r",stdin);
  44. freopen("string.out","w",stdout);
  45. Aireen();
  46. fclose(stdin);
  47. fclose(stdout);
  48. return 0;
  49. }

[日常训练]string的更多相关文章

  1. 「日常训练」ZgukistringZ(Codeforces Round #307 Div. 2 B)

    题意与分析(CodeForces 551B) 这他妈哪里是日常训练,这是日常弟中弟. 题意是这样的,给出一个字符串A,再给出两个字符串B,C,求A中任意量字符交换后(不限制次数)能够得到的使B,C作为 ...

  2. 「日常训练」 Fire!(UVA-11624)

    与其说是训练不如说是重温.重新写了Java版本的代码. import java.util.*; import java.math.*; import java.io.BufferedInputStre ...

  3. 「日常训练」Common Subexpression Elimination(UVa-12219)

    今天做的题目就是抱佛脚2333 懂的都懂. 这条题目干了好几天,最后还是参考别人的代码敲出来了,但是自己独立思考了两天多,还是有收获的. 思路分析 做这条题我是先按照之前的那条题目(The SetSt ...

  4. 集训队日常训练20181117 DIV2

    大佬们一顿操作猛如虎,拼命AC强啊 4262: 区间异或  Time Limit(Common/Java):1000MS/3000MS     Memory Limit:65536KByteTotal ...

  5. [日常训练]article

    Description 小今天来写作文啦! 小非常善于堆砌辞藻.在洋洋洒洒写了一长篇之后,小发现作文中很多段落都似曾相识.小认为,如果一段字符在文章开头,结尾和中间都出现过,那么这段字符就可以被认为是 ...

  6. 日常训练 dfs 之 拓扑排序

    今天被拓扑排序给折磨了一天,主要就是我的一个代码有点小bug,真难找... 先来看看我今天写的题目吧! C. Fox And Names Fox Ciel is going to publish a ...

  7. 日常训练赛 Problem C – Complete Naebbirac’s sequence

    比赛链接https://vjudge.net/contest/256988#status/17111202012/C/0/ 大意:三个操作,使得输入的数中,从1-n,每一个数出现的次数相同. wa代码 ...

  8. 【日常训练】 Help Greg the Dwarf(CodeForces-99E)

    题意与分析 题意是这样的,问你把一个长方形从一个L型街道的一端移动到另一端,固定了该长方形的长,求他的最大宽. 这种问题我是第一次独立解决(以前都是抱队友大腿QAQ),现在没法子只好自己硬着头皮做,看 ...

  9. 【日常训练】Help Victoria the Wise(Codeforces 99C)

    题意与分析 这题意思是这样的:在正方体的六面镶嵌给定颜色的宝石(相同颜色不区分),然后问最多有几种彼此不等价(即各种旋转过后看起来一致)的方案. 其实可以乱搞,因为范围只有720.求出全排列,然后每个 ...

随机推荐

  1. 生成Tab键或逗号分隔的CSV

    <?php header("Content-type:text/csv;charset=utf-8"); header("Content-Disposition:a ...

  2. Unable to simultaneously satisfy constraints.

    在进行版本的迭代更新时,新功能需求需要对主页面的UI进行重新的布局,但是,报了错误,出了好多约束方面的问题: Unable to simultaneously satisfy constraints. ...

  3. Hibernate 系列 03 - 使用Hibernate完成持久化操作

    引导目录: Hibernate 系列教程 目录 康姆昂,北鼻,来此狗.动次打次,Hibernate继续走起. 目录: 使用Hibernate实现按主键查询 使用Hibernate实现数据库的增.删.改 ...

  4. C#中DateTime.Ticks属性及Unix时间戳转换

    1.相关概念 DateTime.Ticks:表示0001 年 1 月 1 日午夜 12:00:00 以来所经历的 100 纳秒数,即Ticks的属性为100纳秒(1Ticks = 0.0001毫秒). ...

  5. Hadoop技巧(02):时间同步

    阅读目录 序 时间同步 系列索引 本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 文章是哥(mephisto)写的,SourceLink 序 在实际部署 ...

  6. 2015-12-01 SQL查询语句基础

    1.查询全体学生的学号与姓名select sno,snamefrom student;3.查询全体学生的详细信息select *from student;4.查询全体学生的姓名及其出生年份select ...

  7. sql 优化

    1.选择最有效率的表名顺序(只在基于规则的优化器中有效): oracle的解析器按照从右到左的顺序处理 from 子句中的表名,from子句中写在最后的表(基础表driving table)将被最先处 ...

  8. dubox首次调用消费者执行两次问题

    dubbox+zookeeper服务开启后 Dubbo的超时重试机制为服务容错.服务稳定提供了比较好的框架支持,但是在一些比较特殊的网络环境下(网络传输慢,并发多)可能由于服务响应慢,Dubbo自身的 ...

  9. linux基本知识1

    ls命令: -l:长格式 文件类型:第1位 -:普通文件 d:目录文件 b:块设备文件(block) c:字符设备文件(character) l:符号链接文件(symbolic link file) ...

  10. 基于UDP的网络编程

    与TCP编程相比较,UDP缺少了connect().listen()及accept()函数,这是由于UDP协议无连接的特性,不用维护TCP的连接.断开等状态. UDP编程框图 API函数 socket ...