题目链接

题意

给定\(N\)个词根,每个长度不超过\(5\). 问长度不超过\(L(L\lt 2^{31})\),只由小写字母组成的,至少包含一个词根的单词,一共可能有多少个?

思路

状态(AC自动机)及状态转移(矩阵快速幂)的想法基本与上一题poj 2778 DNA Sequence 状态及状态转移 AC自动机 矩阵快速幂类似。

不同处有两点:

上一题是问不包含任何一个危险子串的有多少个,这一题是问至少包含一个,直接按上题做法求得答案用总数减去它即可。

**错误做法**:只保留能够通过$fail$指针到达某个单词结尾状态的节点,将其他节点全部删去。
上题中之所以需要删去所有能够到达危险状态的点,是因为它们绝对不能作为中间状态而存在。而本题中不能通过fail指针到达单词结尾的点是可以作为中间状态而存在的,毕竟是要借助它们才能到达结尾状态的。

上一题是求指定长度的,本题是求长度小于等于\(L\)的。

记关系矩阵为\(A\),则上一题是求\(A^n\),而这一题是求$$I+A+A2+...+An$$这也是可以用矩阵快速幂做的,

记\(S_k=I+A+A^2+...+A^{k-1}\),则有

\[\pmatrix{A^k\cr S_k}=\pmatrix{A&0\\I&I}\pmatrix{A^{k-1}\\S_{k-1}}$$就又可以欢乐地用矩阵快速幂做了~

// 此外,从中得到启示,等比数列求和也都可以这么做了,比如这道题里面的$26+26^2+...+26^l$,记$T_k=26+26^2+...+26^{k-1}$,则有
$$\pmatrix{a^k\\T_k}=\pmatrix{26&0\\1&1}\pmatrix{a^{k-1}\\T_{k-1}}\]

但是只能说是自娱自乐一下...。

// 此外,本题的输出是要求模\(2^64\),于是可以直接用\(unsigned\ long\ long\),输出注意是\(\%I64u\)

Code

#include <bits/stdc++.h>
#define SIZE 26
#define maxn 32
using namespace std;
typedef unsigned long long ULL;
int cnt;
typedef struct {
ULL mat[maxn<<1][maxn<<1];
void init(ULL x, int cnt){
memset(mat, 0, sizeof(mat));
for(int i=0; i<cnt; i++) mat[i][i] = x;
}
void print(int cnt) const {
for (int i = 0; i < cnt; ++i) {
for (int j = 0; j < cnt; ++j) printf("%lld ", mat[i][j]); printf("\n");
}
}
} Matrix;
Matrix m0, m1, m2;
ULL add(ULL a, ULL b) { return a + b; }
ULL mul(ULL a, ULL b) { return a * b; }
Matrix mulm(const Matrix& a, const Matrix& b, int cnt) {
Matrix temp;
temp.init(0, cnt);
for (int i = 0; i < cnt; ++i) {
for (int j = 0; j < cnt; ++j) {
for (int k = 0; k < cnt; ++k) temp.mat[i][j] = add(temp.mat[i][j], mul(a.mat[i][k], b.mat[k][j]));
}
}
return temp;
}
Matrix addm(const Matrix& a, const Matrix& b, int cnt) {
Matrix temp;
temp.init(0, cnt);
for (int i = 0; i < cnt; ++i) for (int j = 0; j < cnt; ++j) temp.mat[i][j] = add(a.mat[i][j], b.mat[i][j]);
return temp;
}
Matrix poww(Matrix m, ULL n, int cnt) {
Matrix a = m, ret;
ret.init(1, cnt);
while (n) {
if (n & 1) ret = mulm(ret, a, cnt);
a = mulm(a, a, cnt);
n >>= 1;
}
return ret;
}
int son[maxn][SIZE], fail[maxn], tot;
ULL mat[maxn][maxn];
bool flag[maxn];
void insert(char* s, int len) {
int p = 0;
for (int i = 0; i < len; ++i) {
if (son[p][s[i]-'a'] == -1) {
flag[++tot] = 0;
for (int j = 0; j < SIZE; ++j) son[tot][j] = -1;
son[p][s[i]-'a'] = tot;
}
p = son[p][s[i]-'a'];
}
flag[p] = true;
}
void build() {
queue<int> que;
fail[0] = 0;
for (int i = 0; i < SIZE; ++i) {
if (son[0][i] == -1) son[0][i] = 0;
else {
fail[son[0][i]] = 0;
que.push(son[0][i]);
}
++mat[0][son[0][i]];
}
while (!que.empty()) {
int x = que.front(); que.pop();
for (int i = 0; i < SIZE; ++i) {
if (son[x][i] == -1) son[x][i] = son[fail[x]][i];
else {
fail[son[x][i]] = son[fail[x]][i];
flag[son[x][i]] |= flag[fail[son[x][i]]];
que.push(son[x][i]);
}
++mat[x][son[x][i]];
}
}
}
void init() {
flag[tot = 0] = 0;
memset(mat, 0, sizeof mat);
memset(m0.mat, 0, sizeof m0.mat);
memset(m1.mat, 0, sizeof m1.mat);
memset(m2.mat, 0, sizeof m2.mat);
for (int i = 0; i < SIZE; ++i) son[0][i] = -1;
} int n, l;
char s[10];
int mp[maxn];
void work() {
init();
for (int i = 0; i < n; ++i) {
scanf("%s", s);
insert(s, strlen(s));
}
build(); cnt = 0;
for (int i = 0; i <= tot; ++i) if (!flag[i]) mp[cnt++] = i;
for (int i = 0; i < cnt; ++i) {
for (int j = 0; j < cnt; ++j) {
m0.mat[i][j] = mat[mp[i]][mp[j]];
}
} for (int i = 0; i < cnt; ++i) m0.mat[i+cnt][i] = m0.mat[i+cnt][i+cnt] = 1;
Matrix fnl = poww(m0, l, cnt<<1);
for (int i = cnt; i < (cnt<<1); ++i) {
for (int j = 0; j < cnt; ++j) {
m1.mat[i-cnt][j] = fnl.mat[i][j];
m2.mat[i-cnt][j] = fnl.mat[i][j+cnt];
}
}
Matrix ret = addm(mulm(m1, m0, cnt), m2, cnt);
ULL sub = 0;
for (int i = 0; i < cnt; ++i) sub = add(sub, ret.mat[0][i]); Matrix mm;
mm.mat[0][0] = 26, mm.mat[0][1] = 0, mm.mat[1][0] = 1, mm.mat[1][1] = 1;
Matrix mmfnl = poww(mm, l, 2);
ULL sum = add(mul(26, mmfnl.mat[1][0]), mmfnl.mat[1][1]);
ULL ans = add(sum, -sub);
printf("%I64u\n", ans);
}
int main() {
while (scanf("%d%d", &n, &l) != EOF) work();
return 0;
}

hdu 2243 考研路茫茫——单词情结 AC自动机 矩阵幂次求和的更多相关文章

  1. hdu 2243 考研路茫茫——单词情结 ac自动机+矩阵快速幂

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2243 题意:给定N(1<= N < 6)个长度不超过5的词根,问长度不超过L(L <23 ...

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

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

  3. HDU 2243 考研路茫茫——单词情结(AC自动机+DP+快速幂)

    题目链接 错的上头了... 这题是DNA的加强版,26^1 +26^2... - A^1-A^2... 先去学了矩阵的等比数列求和,学的是第二种方法,扩大矩阵的方法.剩下就是各种模板,各种套. #in ...

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

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

  5. [hdu2243]考研路茫茫——单词情结(AC自动机+矩阵快速幂)

    题意:长度不超过L,只由小写字母组成的,至少包含一个词根的单词,一共可能有多少个. 解题关键:利用补集转化的思想,先求一个词根也不包含的单词个数,然后用总的减去即可.长度不超过L需要用矩阵维数增加一倍 ...

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

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

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

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

  8. HDU2243 考研路茫茫——单词情结 ——AC自动机、矩阵优化

    题目链接:https://vjudge.net/problem/HDU-2243 考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others)    Memor ...

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

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

随机推荐

  1. 一个简单的linux下设置定时执行shell脚本的示例

    很多时候我们有希望服务器定时去运行一个脚本来触发一个操作,比如说定时去备份服务器数据.数据库数据等 不适合人工经常做的一些操作这里简单说下 shell Shell俗称壳,类似于DOS下的command ...

  2. GNU汇编程序框架

    汇编的作用:1.对芯片进行初始化 2. 和C混合编程提升C的运行效率 .section .data < 初始化的数据> .section .bss <未初始化的数据> .sec ...

  3. 关于PHPExcel导出Excel时身份证,数字会导出为科学计数的处理方法

    上次在开发一个项目时,用到PHPExcel导出数据,其中有导出身份证等长串数字时导出的Excel中显示为科学计数方式. 这种显示很不人性化而且量多了修改起来也很麻烦. 这是因为Excel处理数字里默认 ...

  4. 【PHP】Thinkphp 七牛云API对接

    访问一个网站,图片的流量占的比例是非常高的!在你的服务器硬盘上,图片占的容量也是非常高的. 如果要搞一个图片非常多,用户量又很庞大的网站,那么,得花多少钱烧在服务器上? 这种时候,当然要用第三方图片存 ...

  5. 50 道 CSS 基础面试题及答案

    1 介绍一下标准的CSS的盒子模型?与低版本IE的盒子模型有什么不同的? 标准盒子模型:宽度=内容的宽度(content)+ border + padding + margin 低版本IE盒子模型:宽 ...

  6. 数据结构-模式匹配串算法(KMP)

    #include<cstdio> #include<iostream> #include<string> #include<cstring> #incl ...

  7. 最小生成树:HDU1863-畅通工程

    畅通工程 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submissi ...

  8. datatime来计算代码段运行时长

    小知识点:编程中一般都是先乘后除,这样结果更为精确 先定义 DataTime startTime = DataTime.Now; 中间是运行代码 最后TimeSpan ts = DataTime.No ...

  9. 使用Spark Streaming + Kudu + Impala构建一个预测引擎

    随着用户使用天数的增加,不管你的业务是扩大还是缩减了,为什么你的大数据中心架构保持线性增长的趋势?很明显需要一个稳定的基本架构来保障你的业务线.当你的客户处在休眠期,或者你的业务处在淡季,你增加的计算 ...

  10. 无法启动此程序,因为计算机中丢失OgreMain_d.dll。尝试重新安装该程序以解决此问题。

    这个问题很奇怪啊,不明白什么原因? 打开VS2010,打开项目,运行,就提示”无法启动此程序,因为计算机中丢失OgreMain_d.dll.尝试重新安装该程序以解决此问题.“ 然后就去配置环境变量,包 ...