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 ...
随机推荐
- Java之内存分析和String对象
原文地址:http://www.cnblogs.com/devinzhang/archive/2012/01/25/2329463.html 文中 s2后面的注释是错误的,应该是”创建一个对象(堆中) ...
- nginx-upload-module模块实现文件断点续传
导读 每当我们想简单的实现文件上传功能,而又不使用其他的语言(比如PHP.Java),或者想实现文件的断点续传.这个时候Nginx的一个模块nginx-upload-module就能满足我们的需求. ...
- 减小Delphi XE5编译出来的程序体积
默认Delphi XE, XE2, XE3,XE4,XE5, XE6 ... 编译出来的程序体积很大. 一般用两个方法可以很大程度上减少程序体积. 一.在工程中用编译指令禁用RTTI 禁用的方法很简单 ...
- 《ASP.NET1200例》ASP.Net 之Datalist数据删除(支持批量)
.aspx <div> <asp:DataList ID="DataList1" runat="server" Width="355 ...
- location 、history
location.href= location.reload() history.go() 0 1 -1 history.back() history.forward() history.le ...
- python将json格式的数据转换成文本格式的数据或sql文件
python如何将json格式的数据快速的转化成指定格式的数据呢?或者转换成sql文件? 下面的例子是将json格式的数据准换成以#_#分割的文本数据,也可用于生成sql文件. [root@bogon ...
- Java数据类型中String、Integer、int相互间的转换
1.Integer转换成int的方法 Integer i; int k = i.intValue(); 即Integer.intValue(); 2.int转换成Integer int i; Int ...
- HDU 5734 Acperience (公式推导) 2016杭电多校联合第二场
题目:传送门. #include <iostream> #include <algorithm> #include <cstdio> #include <cs ...
- [Android Pro] AndroidStudio导出jar包
reference : http://blog.csdn.net/beijingshi1/article/details/38681281 不像在Eclipse,可以直接导出jar包.Android ...
- 忘记oracle的sys用户密码怎么修改
转分类: Linux 一.忘记除SYS.SYSTEM用户之外的用户的登录密码. 用SYS (或SYSTEM)用户登录: CONN SYS/PASS_WORD AS SYSDBA; 使用如下语句修改 ...