[ CERC 2014 ] Vocabulary
\(\\\)
\(Description\)
给出三个长度分别为 \(lenA,lenB,lenC\) 的三个字符串 \(A,B,C\) ,其中字符集只包括所有小写字母以及 \(?\) 号。
现在将所有 \(?\) 号改为任意小写字母,问有多少种方案,使得 \(A,B,C\) 三个字符串按照字典序排列\((\)相同不算\()?\)
输出方案数对 \(10^9+9\) 取模后的结果。多组询问。
- 字符串总长度\(\le 10^6\)
\(\\\)
\(Solution\)
有趣的预处理题目。
三个串长度不能确定,不能通过数据组数判断复杂度要求,只好按照上界分析,即只有一组数据,做法接近线性。
首先考虑三个串不等长的问题,字典序中规定,一个串的任意长度前缀都比当前串字典序小,所以在不是最长的串后面补上若干个比 \(a\) 还要小的字符即可。
\(\\\)
考虑为了使得最后合法,三个串的字典序在确定 \(?\) 号的时候合法的情况(小于号表示字典序左侧优于右侧):
- \(1:\ A=B=C\)
- \(2:\ A<B=C\)
- \(3:\ A=B<C\)
- \(4:\ A<B<C\)
其他情况会导致在某一位置某两串字典序相反,这样后面不管怎样设置字典序都是反过来的。
\(\\\)
动态规划。
设\(f[i][1/2/3/4]\)表示,当前位置为\(i\),当前位置及以前的所有 \(?\) 号都确定完了之后,使得三个串的字典序关系变为 \(1/2/3/4\) 的方案数。
为了便于初始化,将字符串都向后推一个,然后有\(f[0][1]=1\),答案为\(f[maxlen][4]\)。
考虑转移的过程,合法的转移有:\(1 \to 1/2/3/4\ ,\ 2\to 2/4\ ,\ 3\to 3/4\ ,\ 4\to4\),想不明白可以手玩一下,当前位置每一种情况的字典序的前提是不同的,例如 \(1\) 类情况必须要求前面的位置都为 \(1\) 类情况。
\(\\\)
然后考虑转移的过程,显然我们的转移影响要素有,前一位置状态,以及当前位置三个字符串的字符。
考虑到每次操作统计方案数非常麻烦,而转移只有 \(28^3\times(4+2+2+1)\) 种\((\)后面括号里对应着状态间的转移\()\),不妨对每个转移处理出来方案数。
设 \(g[i][j][x][y][z]\) 表示,要从状态 \(i\) 转移到 \(j\) ,当前位置三个串的字符分别为 \(x,y,z\) 的方案数,预处理就暴力枚举三个字符,注意从上到下字符区间的限制,然后将可以累加的转移方案数累加就好。
然后我们动规的转移就可以直接借用 \(g\) 数组转移了,单组数据复杂度 \(\text O (16N)\)。
\(\\\)
\(Code\)
#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 1000010
#define R register
#define mod 1000000009
using namespace std;
typedef long long ll;
char a[N],b[N],c[N];
ll f[N][4],g[4][4][28][28][28];
int s1[N],s2[N],s3[N],lena,lenb,lenc,len;
inline void prework(){
int l1,r1,l2,r2,l3,r3;
for(R int i=0;i<=27;++i)
for(R int j=0;j<=27;++j)
for(R int k=0;k<=27;++k){
(i==27)?l1=1,r1=26:l1=r1=i;
for(R int x=l1;x<=r1;++x){
(j==27)?l2=1,r2=26:l2=r2=j;
for(R int y=l2;y<=r2;++y){
(k==27)?l3=1,r3=26:l3=r3=k;
for(R int z=l3;z<=r3;++z){
++g[3][3][i][j][k];
if(x==y) ++g[1][1][i][j][k];
if(x<y) ++g[1][3][i][j][k];
if(y==z) ++g[2][2][i][j][k];
if(y<z) ++g[2][3][i][j][k];
if(x==y&&y==z) ++g[0][0][i][j][k];
if(x==y&&y<z) ++g[0][1][i][j][k];
if(x<y&&y==z) ++g[0][2][i][j][k];
if(x<y&&y<z) ++g[0][3][i][j][k];
}
}
}
}
}
inline void init(){
scanf("%s",a); lena=strlen(a);
scanf("%s",b); lenb=strlen(b);
scanf("%s",c); lenc=strlen(c);
len=max(lena,max(lenb,lenc));
for(R int i=0;i<lena;++i) s1[i+1]=(a[i]=='?'?27:a[i]-'a'+1);
for(R int i=lena;i<=len;++i) s1[i+1]=0;
for(R int i=0;i<lenb;++i) s2[i+1]=(b[i]=='?'?27:b[i]-'a'+1);
for(R int i=lenb;i<=len;++i) s2[i+1]=0;
for(R int i=0;i<lenc;++i) s3[i+1]=(c[i]=='?'?27:c[i]-'a'+1);
for(R int i=lenc;i<=len;++i) s3[i+1]=0;
}
int main(){
prework();
int t;
scanf("%d",&t);
while(t--){
init();
for(R int i=0;i<=len;++i)
for(R int j=0;j<4;++j) f[i][j]=0;
f[0][0]=1;
for(R int i=1;i<=len;++i)
for(R int k=0;k<4;++k)
if(f[i-1][k]) for(R int j=0;j<4;++j)
(f[i][j]+=f[i-1][k]*g[k][j][s1[i]][s2[i]][s3[i]])%=mod;
printf("%lld\n",f[len][3]);
}
return 0;
}
[ CERC 2014 ] Vocabulary的更多相关文章
- CERC 2014 (动态树+主席树)
CERC 2014 Pork barrel Problem : n个点m条边有边权的无向图,有q个询问,每次询问权值在[L,R]内的边组成的最小生成树的权值和,强制在线. n <= 1000, ...
- 【CERC 2014 E】2048
题意 2048曾经是一款风靡全球的小游戏. 今天,我们换一种方式来玩这个小游戏. 你有一个双端队列,你只能把元素从左端或从右端放入双端队列中.一旦放入就不得取出.放入后,若队列中有连续两个相同的元素, ...
- ICLR 2014 International Conference on Learning Representations深度学习论文papers
ICLR 2014 International Conference on Learning Representations Apr 14 - 16, 2014, Banff, Canada Work ...
- 漫谈2014年人机交互(CHI)大会
编者按:2014年度以人机交互为主题的顶级会议ACM SIGCHI已经落下帷幕.微软研究院在此次会议的入选论文总数仅次于卡耐基•梅隆大学,位列第二.此次会议中,有哪些创新想法或技术让人眼前一亮?听微软 ...
- 看完SQL Server 2014 Q/A答疑集锦:想不升级都难!
看完SQL Server 2014 Q/A答疑集锦:想不升级都难! 转载自:http://mp.weixin.qq.com/s/5rZCgnMKmJqeC7hbe4CZ_g 本期嘉宾为微软技术中心技术 ...
- SQL Server 2014 新特性——内存数据库
SQL Server 2014 新特性——内存数据库 目录 SQL Server 2014 新特性——内存数据库 简介: 设计目的和原因: 专业名词 In-Memory OLTP不同之处 内存优化表 ...
- 2014年暑假c#学习笔记目录
2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...
- SQL Server 2014聚集列存储索引
转发请注明引用和原文博客(http://www.cnblogs.com/wenBlog) 简介 之前已经写过两篇介绍列存储索引的文章,但是只有非聚集列存储索引,今天再来简单介绍一下聚集的列存储索引,也 ...
- Web 前端攻防(2014版)
在百度 FEX 团队时写的.有次让我写点前端开发中注意的安全规范,结果写着写着就跑题了,写了一堆纯前端实现的攻击方式...当然还有防范措施. 文章就懒得粘过来了~ 直接贴个地址算了:) http:// ...
随机推荐
- 遍历ArrayList数组时可能存在的问题
我们都知道ArrayList类中有个重要的方法是Add(),该方法用于向集合中添加元素,它有一个object类型的参数,表示通过该方法可以向集合中添加任意类型的项,由于ArrayList动态数组中的元 ...
- SAS编程基础 - 逻辑库和数据集
1. SAS逻辑库 1.1 创建SAS逻辑库: libname lb 'F:\Data_Model'; libname是关键字,lb是创建的逻辑库的名称,引号内的内容是目录路径,最后一个分号结束程序语 ...
- 关于 TCP 并发连接的几个思考题与试验
http://blog.csdn.net/solstice/article/details/6579232
- 实战c++中的vector系列--emplace_back造成的引用失效
上篇将了对于struct或是class为何emplace_back要优越于push_back,可是另一些细节没有提及.今天就谈一谈emplace_back造成的引用失效. 直接撸代码了: #inclu ...
- mysql 经常使用命令整理总结
#改动字段类型 alter table `table_name` modify column ip varchar(50); #添加字段 alter table `table_name` add ip ...
- td里面嵌套img标签后如何消除图片间隔
td里面嵌套image标签后如何消除图片间隔 CreateTime--2018年3月7日16:18:12 Author:Marydon 情景还原: <body> <div sty ...
- SQL Server游标 C# DataTable.Select() 筛选数据 什么是SQL游标? SQL Server数据类型转换方法 LinQ是什么? SQL Server 分页方法汇总
SQL Server游标 转载自:http://www.cnblogs.com/knowledgesea/p/3699851.html. 什么是游标 结果集,结果集就是select查询之后返回的所 ...
- Woody的逻辑游戏--怎样换轮胎
题目:有一个做长途运输的司机要出发了,他用作运输的车是三轮车.轮胎的寿命是2万里,如今他要进行5万里的长途运输.计划用8个轮胎完毕运输任务,如何才干做到呢? 首先将轮胎从1-8依次编号,然后例如以下所 ...
- jeasyui控件事件和方法的使用方法
1.事件是在页面加载后就注册绑定: $(function () { ocr(); }); function ocr() { $('#dgTeacher').datagrid({ onClickRow: ...
- MySQL 基本信息的查询(初始化配置信息 my.ini)
0. my.ini MySQL 的初始化配置信息 mysql 启动时会读取该配置文件,如果按照默认方式安装 mysql 的话,该配置文件在: C:\ProgramData\MySQL\MySQL Se ...