HDU2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)
与POJ2778一样。这题是求长度不超过n且包含至少一个词根的单词总数。
长度不超过n的单词总数记为Sn,长度不超过n不包含词根的单词总数记为Tn。
答案就是,Sn-Tn。
Sn=26+262+263+...+26n
Tn=A+A2+A3+...+An (A为AC自动机构造出来的矩阵)
可以构造矩阵用快速幂求出Sn和Tn:
$$ \begin{bmatrix} 26 & 1 \\ 0 & 1 \end{bmatrix} \times \begin{bmatrix} S_n \\ 26 \end{bmatrix} = \begin{bmatrix} S_{n+1} \\ 26 \end{bmatrix}$$
$$ \begin{bmatrix} A & E \\ 0 & E \end{bmatrix} \times \begin{bmatrix} T_n \\ A \end{bmatrix} = \begin{bmatrix} T_{n+1} \\ A \end{bmatrix}$$
通过 $ \begin{bmatrix} 26 & 1 \\ 0 & 1 \end{bmatrix} ^n \times \begin{bmatrix} S_0 \\ 26 \end{bmatrix} = \begin{bmatrix} S_n \\ 26 \end{bmatrix}$ 即可得到Sn,其中S0=0,Tn同理。
另外题目结果mod 264这个直接把变量定义为unsigned __int64即可,溢出位数自动舍去。
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int tn,ch[][],fail[];
bool flag[];
void insert(char *s){
int x=;
for(int i=; s[i]; ++i){
int y=s[i]-'a';
if(ch[x][y]==) ch[x][y]=++tn;
x=ch[x][y];
}
flag[x]=;
}
void init(int x){
memset(fail,,sizeof(fail));
queue<int> que;
for(int i=; i<; ++i){
if(ch[][i]) que.push(ch[][i]);
}
while(!que.empty()){
int x=que.front(); que.pop();
for(int i=; i<; ++i){
if(ch[x][i]) que.push(ch[x][i]),fail[ch[x][i]]=ch[fail[x]][i];
else ch[x][i]=ch[fail[x]][i];
flag[ch[x][i]]|=flag[ch[fail[x]][i]];
}
}
}
void init(){
memset(fail,,sizeof(fail));
queue<int> que;
for(int i=; i<; ++i){
if(ch[][i]) que.push(ch[][i]);
}
while(!que.empty()){
int now=que.front(); que.pop();
for(int i=; i<; ++i){
if(ch[now][i]) que.push(ch[now][i]),fail[ch[now][i]]=ch[fail[now]][i];
else ch[now][i]=ch[fail[now]][i];
flag[ch[now][i]]|=flag[ch[fail[now]][i]];
}
}
}
struct Mat{
unsigned long long m[][];
int n;
};
Mat operator*(const Mat &m1,const Mat &m2){
Mat m={};
m.n=m1.n;
for(int i=; i<m.n; ++i){
for(int j=; j<m.n; ++j){
for(int k=; k<m.n; ++k) m.m[i][j]+=m1.m[i][k]*m2.m[k][j];
}
}
return m;
}
int main(){
int n,l;
char str[];
while(~scanf("%d%d",&n,&l)){
tn=;
memset(ch,,sizeof(ch));
memset(flag,,sizeof(flag));
while(n--){
scanf("%s",str);
insert(str);
}
init();
Mat se={},sm={};
se.n=sm.n=;
for(int i=; i<; ++i) se.m[i][i]=;
sm.m[][]=; sm.m[][]=; sm.m[][]=;
n=l;
while(n){
if(n&) se=se*sm;
sm=sm*sm;
n>>=;
}
unsigned long long tot=se.m[][]*; Mat te={},tm={};
te.n=tm.n=tn+<<;
for(int i=; i<te.n; ++i) te.m[i][i]=;
for(int i=; i<=tn; ++i){
tm.m[i+tn+][i+tn+]=tm.m[i][i+tn+]=;
}
for(int i=; i<=tn; ++i){
if(flag[i]) continue;
for(int j=; j<; ++j){
if(flag[ch[i][j]]) continue;
++tm.m[i][ch[i][j]];
}
}
Mat tmp=tm; tmp.n=tn+;
n=l;
while(n){
if(n&) te=te*tm;
tm=tm*tm;
n>>=;
}
Mat tmp2; tmp2.n=tn+;
for(int i=; i<=tn; ++i){
for(int j=tn+; j<te.n; ++j) tmp2.m[i][j-tn-]=te.m[i][j];
}
tmp=tmp*tmp2;
unsigned long long res=;
for(int i=; i<=tn; ++i){
res+=tmp.m[][i];
}
printf("%llu\n",tot-res);
}
return ;
}
HDU2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)的更多相关文章
- [hdu2243]考研路茫茫——单词情结(AC自动机+矩阵快速幂)
题意:长度不超过L,只由小写字母组成的,至少包含一个词根的单词,一共可能有多少个. 解题关键:利用补集转化的思想,先求一个词根也不包含的单词个数,然后用总的减去即可.长度不超过L需要用矩阵维数增加一倍 ...
- hdu 2243 考研路茫茫——单词情结 ac自动机+矩阵快速幂
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2243 题意:给定N(1<= N < 6)个长度不超过5的词根,问长度不超过L(L <23 ...
- HDU 2243 考研路茫茫——单词情结(AC自动机+DP+快速幂)
题目链接 错的上头了... 这题是DNA的加强版,26^1 +26^2... - A^1-A^2... 先去学了矩阵的等比数列求和,学的是第二种方法,扩大矩阵的方法.剩下就是各种模板,各种套. #in ...
- HDU2243 考研路茫茫——单词情结 ——AC自动机、矩阵优化
题目链接:https://vjudge.net/problem/HDU-2243 考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others) Memor ...
- hdu_2243_考研路茫茫——单词情结(AC自动机+矩阵)
题目链接:hdu_2243_考研路茫茫——单词情结 题意: 让你求包含这些模式串并且长度不小于L的单词种类 题解: 这题是poj2788的升级版,没做过的强烈建议先做那题. 我们用poj2778的方法 ...
- hdu 2243 考研路茫茫——单词情结 AC自动机 矩阵幂次求和
题目链接 题意 给定\(N\)个词根,每个长度不超过\(5\). 问长度不超过\(L(L\lt 2^{31})\),只由小写字母组成的,至少包含一个词根的单词,一共可能有多少个? 思路 状态(AC自动 ...
- HDU-2243 考研路茫茫——单词情结(AC自动机)
题目大意:给n个单词,长度不超过L的单词有多少个包含n个单词中的至少一个单词. 题目分析:用长度不超过L的单词书目减去长度在L之内所有不包含任何一个单词的书目. 代码如下: # include< ...
- hdu 2243 考研路茫茫——单词情结(AC自动+矩阵)
考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- hdu2243 考研路茫茫——单词情结【AC自动机】【矩阵快速幂】
考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
随机推荐
- 淘宝(阿里百川)手机客户端开发日记第六篇 Service详解(四)
DEMO1:在Activity里声明一个回调方法,当service完成任务后,调用这个回调方法. 首先,我们先继承service,来创建服务,代码如下: package com.example.ser ...
- Linux tcp_wrappers 详解
tcp_wrappers是linux中一个安全机制[TCP_wrappers防火墙],一定程度上限制某种服务的访问权限,达到了保护系统的目的一. 要想用好tcp_wrappers,首先检查某种服务是否 ...
- vim实用技巧
<1> 删除空格: :% s/ //gi #正则为一个空格,替换为空,全局匹配. <2> 删除空行: :g /^\n*$/ d #g为global 正则为:行开始+换 ...
- First Position of Target
For a given sorted array (ascending order) and a target number, find the first index of this number ...
- dom 中事件
阻止表单提交: function aa(){ return false; } function bb(event){ event.preventDefault(); } 事件不再派发: <!DO ...
- Maven发布web项目到tomcat
在java开发中经常要引入很多第三方jar包:然而无论是java web开发还是其他java项目的开发经常会由于缺少依赖包引来一些不必要的异常.常常也是因为这样的原因导致许多简单的缺包和版本问题耗费大 ...
- 解决kettle配置文件中的中文乱码
在日常开发中有时候配置文件会出现中文(如config.properties 里有中文),为了避免出现乱码,因而要转成unicode编码. 1.在设置变量的javascript(转换中的JavaScri ...
- 【转】kettle 的内存设置及输出日志的时间类型
本文转载自:http://blog.csdn.net/dqswuyundong/archive/2010/10/19/5952004.aspx 设置kettle的内存 REM ************ ...
- mysql cluster 运行的必备条件
1.由于同步复制一共需要4次消息传递,故mysql cluster的数据更新速度比单机mysql要慢.所以mysql cluster要求运行在千兆以上的局域网内,节点可以采用双网卡,节点组之间采用直 ...
- 4.python函数基础
一.函数 1.函数简介 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但 ...