题意:找出所有长度不大于L的,包含至少一个模式串的主串的个数。

思路:和2778类似,但是这里求1~L所有长度的种数。所以我们只要求出来不包含的所有个数就行。

假设AC自动机上所有节点的邻接矩阵为A,那么答案为$\sum_{i=1}^n 26^i - \sum_{i=1}^n A^i$。

因为L有点大,那么我们可以直接用矩阵快速幂来求:

令$S_n = \sum_{i=1}^n 26^i ,T_n = \sum_{i=1}^n A^i$

$$ \left[ \begin{matrix} T_{n-1} & A \\ 0 & 0 \end{matrix} \right] * \left[ \begin{matrix} A & 0 \\ E & E \end{matrix} \right] = \left[ \begin{matrix} T_{n} & A \\ 0 & 0 \end{matrix} \right]$$

$$ \left[ \begin{matrix} S_{n-1} & 26 \\ 0 & 0 \end{matrix} \right] * \left[ \begin{matrix} 26 & 0 \\ 1 & 1 \end{matrix} \right] = \left[ \begin{matrix} S_{n} & 26 \\ 0 & 0 \end{matrix} \right]$$

求$T_n$的时候直接开一个大矩阵求就行了

代码:

#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 30 + 5;
const int M = 50 + 5;
const ull seed = 131;
const double INF = 1e20;
const int MOD = 100000;
int n;
ll L;
struct Mat{ull s[maxn * 2][maxn * 2];void init(){for(int i = 0; i < maxn * 2; i++)for(int j = 0; j < maxn * 2; j++)s[i][j] = 0;}
};
Mat mul(Mat &a, Mat &b, int tn){Mat t;t.init();for(int i = 0; i < tn; i++){for(int j = 0; j < tn; j++){for(int k = 0; k < tn; k++){t.s[i][j] = t.s[i][j] + a.s[i][k] * b.s[k][j];}}}return t;
}
Mat ppow(Mat a, ll b, int tn){Mat ret;ret.init();for(int i = 0; i < maxn * 2; i++) ret.s[i][i] = 1;while(b){if(b & 1) ret = mul(ret, a, tn);a = mul(a, a, tn);b >>= 1;}return ret;
}
struct Aho{struct state{int next[26];int fail, cnt;}node[maxn];int size;queue<int> q;void init(){size = 0;newtrie();while(!q.empty()) q.pop();}int newtrie(){memset(node[size].next, 0, sizeof(node[size].next));node[size].cnt = node[size].fail = 0;return size++;}void insert(char *s){int len = strlen(s);int now = 0;for(int i = 0; i < len; i++){int c = s[i] - 'a';if(node[now].next[c] == 0){node[now].next[c] = newtrie();}now = node[now].next[c];}node[now].cnt = 1;}void build(){node[0].fail = -1;q.push(0);while(!q.empty()){int u = q.front();q.pop();if(node[node[u].fail].cnt && u) node[u].cnt = 1;   //都不能取for(int i = 0; i < 26; i++){if(!node[u].next[i]){if(u == 0)node[u].next[i] = 0;elsenode[u].next[i] = node[node[u].fail].next[i];}else{if(u == 0) node[node[u].next[i]].fail = 0;else{int v = node[u].fail;while(v != -1){if(node[v].next[i]){node[node[u].next[i]].fail = node[v].next[i];break;}v = node[v].fail;}if(v == -1) node[node[u].next[i]].fail = 0;}q.push(node[u].next[i]);}}}}ull query(){Mat A;A.init();for(int i = 0; i < size; i++){for(int j = 0; j < 26; j++){if(node[node[i].next[j]].cnt == 0){A.s[i][node[i].next[j]]++;}}}Mat a, b;a.init(), b.init();for(int i = 0; i < size; i++){for(int j = 0; j < size; j++){a.s[i][j] = a.s[i][j + size] = b.s[i][j] = A.s[i][j];}}for(int i = 0; i < size; i++){b.s[i + size][i] = b.s[i + size][i + size] = 1;}b = ppow(b, L - 1, 2 * size);a = mul(a, b, 2 * size);ull ret = 0;for(int i = 0; i < size; i++){if(node[i].cnt == 0) ret += a.s[0][i];}return ret;}}ac;
char s[20];
int main(){while(~scanf("%d%lld", &n, &L)){ull ans = 0;Mat a, b;a.init(), b.init();a.s[0][0] = a.s[0][1] = 26;b.s[0][0] = 26, b.s[1][0] = 1, b.s[1][1] = 1;b = ppow(b, L - 1, 4);a = mul(a, b, 4);ans = a.s[0][0];ac.init();while(n--){scanf("%s", s);ac.insert(s);}ac.build();ull ret = ac.query();cout << ans - ret << endl;}return 0;
}

转载于:https://www.cnblogs.com/KirinSB/p/11181050.html

HDU 2243 考研路茫茫——单词情结(AC自动机 + 矩阵快速幂)题解相关推荐

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

    题目链接:点击查看 题目大意:给出 n 个词根,现在要求出长度不大于 len 的单词中,有多少单词包含至少一个词根 题目分析:如果我们反过来想,也就是求出来总的单词数,然后减去不包含词根的单词数,剩下 ...

  2. HDU -2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)

    题目链接 思路 假设让求长度为LLL且不包含词根的个数,对所有的词根建acacac自动机,然后用矩阵MMM表示可转移状态,最后最快速幂即可. 如何求长度不超过LLL且不包含LLL且不包含词根的个数,可 ...

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

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

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

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

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

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

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

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

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

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

  8. HDU 2243 考研路茫茫——单词情结(自动机)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2243 题意:给出m个串,问有多少不大于n的串至少包含m个串中的一个? 思路:首先求出不包含m个串的长度 ...

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

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

  10. 【HDU No. 2243】单词情结 考研路茫茫——单词情结

    [HDU No. 2243]单词情结 考研路茫茫--单词情结 杭电OJ 题目地址 [题意] 单词和词根仅由小写字母组成.给定N个词根,求长度不超过L 且至少包含一个词根的单词可能有多少个? 若有两个词 ...

最新文章

  1. java 很垃圾_JAVA吧真的很垃圾!!!
  2. 【Nutch2.2.1源代码分析之4】Nutch加载配置文件的方法
  3. echarts地图在ie浏览器上不显示
  4. 使用NAT网关轻松为单台云服务器设置多个公网IP
  5. 关于select的描述计算机,计算机二级考试MySQL数据库每日一练 12月21日
  6. 2021四川高考成绩位次查询,2021年四川高考位次查询及一分一段表排名查询
  7. .php on line 0,控制台运行php报错 undefined symbol: gdImageCreateFromJpeg in Unknown on line 0 解决方法...
  8. Spring Boot 集成undertow作为web容器分析
  9. 华为端口聚合命令_华为交换机链路聚合命令
  10. 在eclipse环境中配置hadoop开发环境遇到的问题
  11. c#实现文件转base64和base64转文件(文件为任意格式)
  12. java oracle11g jar_oracle11g驱动jar包下载
  13. 单片机C51 之(1)简介
  14. 黑客通常可以分为以下8种类型
  15. 神舟战神换cpu教程_神舟战神做工如何?神舟战神K650D-A29拆机图解教程
  16. 叶俊|知行合一创纪录|杭州创纪录企业管理咨询有限公司董事长简介
  17. 为什么我不能像在Linux和OS X上那样在Windows上更改使用中的文件?
  18. 鸿蒙系统教程,麒麟9000+鸿蒙操作系统,华为新平板有点牛
  19. Linux C语言调用C++动态链接库-改
  20. at com.android.xiong.aysnctasktest.MainActivity$PageTask.onPostExecute(MainActivity.java:116)

热门文章

  1. 你以为海淘产品能逃过海关法眼?大数据技术一网打尽
  2. KVM虚拟化笔记(十)------kvm虚拟机扩充磁盘空间
  3. Office远程代码执行漏洞CVE-2017-8570 大部分版本受影响 PoC已经公开
  4. HTML DOM 基础
  5. PC-启动慢的解决好方法!
  6. jquery砸金蛋 高仿阿里旅游砸金蛋
  7. 蓝桥杯——基础练习之字母图形
  8. struts响应用户请求的工作流程
  9. 在SQUIRREL中使用PHOENIX操作HBASE——创建表和视图
  10. 超详细java中的ClassLoader详解