背单词,始终是复习英语的重要环节。在荒废了3年大学生涯后,Lele也终于要开始背单词了。
一天,Lele在某本单词书上看到了一个根据词根来背单词的方法。比如"ab",放在单词前一般表示"相反,变坏,离去"等。



于是Lele想,如果背了N个词根,那这些词根到底会不会在单词里出现呢。更确切的描述是:长度不超过L,只由小写字母组成的,至少包含一个词根的单词,一共可能有多少个呢?这里就不考虑单词是否有实际意义。



比如一共有2个词根 aa 和 ab ,则可能存在104个长度不超过3的单词,分别为

(2个) aa,ab,

(26个)aaa,aab,aac...aaz,

(26个)aba,abb,abc...abz,

(25个)baa,caa,daa...zaa,

(25个)bab,cab,dab...zab。



这个只是很小的情况。而对于其他复杂点的情况,Lele实在是数不出来了,现在就请你帮帮他。

Input本题目包含多组数据,请处理到文件结束。

每组数据占两行。

第一行有两个正整数N和L。(0<N<6,0<L<2^31)

第二行有N个词根,每个词根仅由小写字母组成,长度不超过5。两个词根中间用一个空格分隔开。

Output对于每组数据,请在一行里输出一共可能的单词数目。

由于结果可能非常巨大,你只需要输出单词总数模2^64的值。

Sample Input

2 3
aa ab
1 2
a

Sample Output

104
52

先找出来长度小于等于L的串,一共有多少个。然后找出来长度小于等于L的串不包含模式串有多少个

两者之差就是答案

题意:
问出现这几个模式串,长度小于等于L的字符串数量有多少

题解:

建议提前看一下DNA Sequence POJ - 2778
DNA Sequence POJ - 2778(问不出现这几个模式串,长度等于L的字符串数量有多少) 这道题差不多。
只需要转化一下:
先求出来长度小于等于L所有串的数量,然后再求一下不出现这几个模式串,长度小于等于L的字符串数量有多少
假设用ac自动机跑出来的矩阵是A
那么就求出来A,A^1,A^2...A^L.每一个矩阵第一行之和。

这就只需要在A矩阵中增加一列,这一列都赋值为1.在对应也要把增加那一行的其他位置赋值为0

例如

原来A=  | 1 2 |       =>>   转化后    A= |1 2 1 |

| 3 4 |                                    | 3 4 1 |

|0 0 1 |

这样最后跑出来的A^L的第一行所有数之和就是最后答案

至于为什么,看下面:

全部串的数量:
26^1 + 26^2 + 26^3 + … + 26^n,也用矩阵快速幂计算。f(n) = 26 * f(n - 1) + 26。
| f(n - 1) 1 |
| 0 0        |
系数矩阵:
| 26 0 |
| 26 1 |
相乘得到:
| f(n) 1 |
| 0 0    |

两者之差就是结果

代码:

  1 #include<stdio.h>
2 #include<iostream>
3 #include<string.h>
4 #include<algorithm>
5 #include<queue>
6 using namespace std;
7 const int maxn=70;
8 const int N=26;
9 const int mod=100000;
10 typedef long long ll;
11 typedef unsigned long long ull;
12 ull m;
13 struct Matrix
14 {
15 unsigned long long mat[40][40];
16 int n;
17 Matrix(){}
18 Matrix(int _n)
19 {
20 n=_n;
21 for(int i=0;i<n;i++)
22 for(int j=0;j<n;j++)
23 mat[i][j] = 0;
24 }
25 Matrix operator *(const Matrix &b)const
26 {
27 Matrix ret = Matrix(n);
28 for(int i=0;i<n;i++)
29 for(int j=0;j<n;j++)
30 for(int k=0;k<n;k++)
31 ret.mat[i][j]+=mat[i][k]*b.mat[k][j];
32 return ret;
33 }
34 };
35 unsigned long long pow_m(unsigned long long a,int n)
36 {
37 unsigned long long ret=1;
38 unsigned long long tmp = a;
39 while(n)
40 {
41 if(n&1)ret*=tmp;
42 tmp*=tmp;
43 n>>=1;
44 }
45 return ret;
46 }
47 Matrix pow_M(Matrix a,int n)
48 {
49 Matrix ret = Matrix(a.n);
50 for(int i=0;i<a.n;i++)
51 ret.mat[i][i] = 1;
52 Matrix tmp = a;
53 while(n)
54 {
55 if(n&1)ret=ret*tmp;
56 tmp=tmp*tmp;
57 n>>=1;
58 }
59 return ret;
60 }
61 struct Trie
62 {
63 ull next[maxn][N],fail[maxn],ends[maxn];
64 ull root,L;
65 ull New_node() //创建一个新节点
66 {
67 for(ull i=0; i<N; ++i)
68 {
69 next[L][i]=-1;
70 }
71 ends[L++]=0;
72 return L-1;
73 }
74 void init() //创建根节点
75 {
76 L=0;
77 root=New_node();
78 }
79 void inserts(char s[]) //往字典树里面插入新字符串
80 {
81 ull len=strlen(s);
82 ull now=root;
83 for(ull i=0; i<len; ++i)
84 {
85 if(next[now][s[i]-'a']==-1)
86 next[now][s[i]-'a']=New_node();
87 now=next[now][s[i]-'a'];
88 }
89 ends[now]=1;
90 }
91 void build()
92 {
93 queue<ull>r;
94 fail[root]=root;
95 for(ull i=0; i<N; ++i)
96 {
97 if(next[root][i]==-1)
98 {
99 next[root][i]=root;
100 }
101 else
102 {
103 fail[next[root][i]]=root;
104 r.push(next[root][i]);
105 }
106 }
107 while(!r.empty())
108 {
109 ull now=r.front();
110 r.pop();
111 if(ends[fail[now]])
112 {
113 ends[now]=1;
114 }
115 for(ull i=0; i<N; ++i)
116 {
117 if(next[now][i]==-1)
118 {
119 next[now][i]=next[fail[now]][i]; //叶节点处没有设置失败节点而是往next上接了一段,这个时候
120 //这个fail里面的值已经在下面的else里面放过东西了
121 }
122 else
123 {
124 fail[next[now][i]]=next[fail[now]][i]; //此节点的子节点的失败节点就是此节点失败节点对应字符位置
125 r.push(next[now][i]);
126 }
127 }
128 }
129 }
130 Matrix Build_c()
131 {
132 Matrix res=Matrix(L+1);
133 for(ull i=0; i<L; ++i)
134 {
135 for(ull j=0; j<N; ++j)
136 {
137 if(ends[next[i][j]]==0)
138 {
139 res.mat[i][next[i][j]]++;
140 }
141 }
142 }
143 for(ull i=0;i<L+1;++i)
144 res.mat[i][L]=1;
145 return res;
146 }
147 };
148 char s[10];
149 Trie ac;
150 Matrix pow_M(Matrix a,ull n)
151 {
152 Matrix ret = Matrix(a.n);
153 for(ull i = 0; i < ret.n; i++)
154 ret.mat[i][i]=1;
155 Matrix tmp=a;
156 while(n)
157 {
158 if(n&1)ret=ret*tmp;
159 tmp=tmp*tmp;
160 n>>=1;
161 }
162 return ret;
163 }
164 int main()
165 {
166 ull n;
167 while(~scanf("%llu%llu",&n,&m))
168 {
169 ac.init();
170 while(n--)
171 {
172 scanf("%s",s);
173 ac.inserts(s);
174 }
175 Matrix two=Matrix(2); /*求出总共有多少单词数*/
176 two.mat[0][0]=26;
177 two.mat[0][1]=1;
178 two.mat[1][1]=1;
179 two=pow_M(two,m);
180 ull tot=two.mat[0][1]*26;
181
182 ac.build(); /*求不满足题意得单词数量*/
183 Matrix ans=ac.Build_c();
184 ans=pow_M(ans,m);
185 ull sum=0;
186 for(ull i=0;i<ans.n;++i)
187 sum+=ans.mat[0][i];
188 sum--;
189
190 printf("%llu\n",tot-sum);
191 }
192 return 0;
193 }

考研路茫茫——单词情结 HDU - 2243 AC自动机 && 矩阵快速幂的更多相关文章

  1. 考研路茫茫――单词情结 HDU - 2243(ac自动机 + 矩阵快速幂)

    考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  2. 考研路茫茫--单词情结 - HDU 2243(AC自动机+矩阵乘法)

    分析:与poj的2778差不多的,求出来所有的情况然后减去不包含的就行了,这次使用了一下kuangbin的那种自动机写法,确实还不错,因为尤是在建立矩阵的时候更加方便.   代码如下: ======= ...

  3. POJ - 2778 ~ HDU - 2243 AC自动机+矩阵快速幂

    这两题属于AC自动机的第二种套路通过矩阵快速幂求方案数. 题意:给m个病毒字符串,问长度为n的DNA片段有多少种没有包含病毒串的. 根据AC自动机的tire图,我们可以获得一个可达矩阵. 关于这题的t ...

  4. hdu 2243 考研路茫茫——单词情结(AC自动+矩阵)

    考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  5. HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵)

    考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  6. hdu 2243 考研路茫茫——单词情结 AC自动机 矩阵幂次求和

    题目链接 题意 给定\(N\)个词根,每个长度不超过\(5\). 问长度不超过\(L(L\lt 2^{31})\),只由小写字母组成的,至少包含一个词根的单词,一共可能有多少个? 思路 状态(AC自动 ...

  7. HDU 2243 考研路茫茫——单词情结

    考研路茫茫——单词情结 Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID ...

  8. HDU 2243 考研路茫茫——单词情结 求长度小于等于L的通路总数的方法

    http://acm.hdu.edu.cn/showproblem.php?pid=2243 这是一题AC自动机 + 矩阵快速幂的题目, 首先知道总答案应该是26^1 + 26^2 + 26^3 .. ...

  9. hdu_2243_考研路茫茫——单词情结(AC自动机+矩阵)

    题目链接:hdu_2243_考研路茫茫——单词情结 题意: 让你求包含这些模式串并且长度不小于L的单词种类 题解: 这题是poj2788的升级版,没做过的强烈建议先做那题. 我们用poj2778的方法 ...

随机推荐

  1. mac配置Android SDK

    下载地址:http://tools.android-studio.org/index.php/sdk 2.找到tools文件夹 选中android-sdk-macosx包下的tools文件夹,按com ...

  2. 【Git】5、Git如何提交代码到远程仓库

    提交代码:如何把修改后的代码提交到远程仓库 文章目录 提交代码:如何把修改后的代码提交到远程仓库 1.同步远程代码 2.检查改动文件 3.添加文件到缓存 4.提交代码 5.推送代码 6.我的整个流程 ...

  3. 【Spring】XML方式实现(无参构造 有参构造)和注解方式实现 IoC

    文章目录 Spring IoC的实现方式 XML方式实现 通过无参构造方法来创建 1.编写一个User实体类 2.编写我们的spring文件 3.测试类 UserTest.java 4.测试结果 通过 ...

  4. oracle RAC和RACOneNode之间的转换

    Convert RAC TO RACOneNode 1.查看资源状态 [grid@rac01 ~]$ crsctl status res -t 从这里看到,数据库的名字叫racdb 2.查看实例 [o ...

  5. C#实现一个弹窗监控小程序

    一..实现弹窗淡入淡出等效果即弹窗自动关闭 技术要点: 1.弹窗效果(淡入淡出,自下而上滑入)使用WIN API实现 2.弹出的窗体在一定时间后,自动关闭使用一个timer实现,弹窗开始是,打开tim ...

  6. 图像分割论文 | DRN膨胀残差网络 | CVPR2017

    文章转自:同作者个人微信公众号[机器学习炼丹术].欢迎交流沟通,共同进步,作者微信:cyx645016617 论文名称:'Dilated Residual Networks' 论文链接:https:/ ...

  7. Java流程控制与Scanner类的使用

    Java流程控制与Scanner类的使用 Scanner类 Scanner类可以使程序接受键盘输入,实现人机交互 一个完整的Scanner的使用例子: //创建一个扫描器对象,用于接收键盘数据 Sca ...

  8. 从零开始学spring源码之xml解析(二):默认标签和自定义标签解析

    默认标签: 上一篇说到spring的默认标签和自定义标签,发现这里面东西还蛮多的.决定还是拆开来写.今天就来好好聊聊这两块是怎么玩的,首先我们先看看默认标签: private void parseDe ...

  9. SpringBoot 自动配置:Spring Data JPA

    前言 不知道从啥时候开始项目上就一直用MyBatis,其实我个人更新JPA些,因为JPA看起来OO的思想更强烈些,所以这才最近把JPA拿出来再看一看,使用起来也很简单,除了定义Entity实体外,声明 ...

  10. centos 7.0 ping百度提示:ping: www.baidu.com: Name or service not known

    解决方法一: 添加dns服务器 vi /etc/resolv.conf 在文件中添加如下两行: nameserver 8.8.8.8 nameserver 8.8.4.4 保存退出,重启服务器.之后再 ...