HDU 2243 考研路茫茫――单词情结 ——(AC自动机+矩阵快速幂)
和前几天做的AC自动机类似。
思路简单但是代码200余行。。
假设solve_sub(i)表示长度为i的不含危险单词的总数。
最终答案为用总数(26^1+26^2+...+26^n)减去(solve_sub(1)+solve_sub(2)+...+solve_sub(n))。前者构造f[i]=f[i-1]*26+26然后矩阵快速幂即可(当然也可以分治的方法)。后者即构造出dp矩阵p,然后计算(p^1+p^2+...+p^n),对其分治即可。
代码如下:
- #include <stdio.h>
- #include <algorithm>
- #include <string.h>
- #include <vector>
- #include <queue>
- #include <iostream>
- using namespace std;
- const int MAX_Tot = + ;
- const int mod = ;
- typedef unsigned long long ull;
- int m,n;
- struct matrix
- {
- ull e[MAX_Tot][MAX_Tot];
- int n,m;
- matrix() {}
- matrix(int _n,int _m): n(_n),m(_m) {memset(e,,sizeof(e));}
- matrix operator * (const matrix &temp)const
- {
- matrix ret = matrix(n,temp.m);
- for(int i=;i<=ret.n;i++)
- {
- for(int j=;j<=ret.m;j++)
- {
- for(int k=;k<=m;k++)
- {
- ret.e[i][j] += e[i][k]*temp.e[k][j];
- }
- }
- }
- return ret;
- }
- matrix operator + (const matrix &temp)const
- {
- matrix ret = matrix(n,m);
- for(int i=;i<=n;i++)
- {
- for(int j=;j<=m;j++)
- {
- ret.e[i][j] += e[i][j]+temp.e[i][j];
- }
- }
- return ret;
- }
- void getE()
- {
- for(int i=;i<=n;i++)
- {
- for(int j=;j<=m;j++)
- {
- e[i][j] = i==j?:;
- }
- }
- }
- };
- matrix qpow(matrix temp,int x)
- {
- int sz = temp.n;
- matrix base = matrix(sz,sz);
- base.getE();
- while(x)
- {
- if(x & ) base = base * temp;
- x >>= ;
- temp = temp * temp;
- }
- return base;
- }
- matrix solve(matrix a, int k)
- {
- if(k == ) return a;
- int n = a.n;
- matrix temp = matrix(n,n);
- temp.getE();
- if(k & )
- {
- matrix ex = qpow(a,k);
- k--;
- temp = temp + qpow(a,k/);
- return temp * solve(a,k/) + ex;
- }
- else
- {
- temp = temp + qpow(a,k/);
- return temp * solve(a,k/);
- }
- }
- struct Aho
- {
- struct state
- {
- int nxt[];
- int fail,cnt;
- }stateTable[MAX_Tot];
- int size;
- queue<int> que;
- void init()
- {
- while(que.size()) que.pop();
- for(int i=;i<MAX_Tot;i++)
- {
- memset(stateTable[i].nxt,,sizeof(stateTable[i].nxt));
- stateTable[i].fail = stateTable[i].cnt = ;
- }
- size = ;
- }
- void insert(char *s)
- {
- int n = strlen(s);
- int now = ;
- for(int i=;i<n;i++)
- {
- char c = s[i];
- if(!stateTable[now].nxt[c-'a'])
- stateTable[now].nxt[c-'a'] = size++;
- now = stateTable[now].nxt[c-'a'];
- }
- stateTable[now].cnt = ;
- }
- void build()
- {
- stateTable[].fail = -;
- que.push();
- while(que.size())
- {
- int u = que.front();que.pop();
- for(int i=;i<;i++)
- {
- if(stateTable[u].nxt[i])
- {
- if(u == ) stateTable[stateTable[u].nxt[i]].fail = ;
- else
- {
- int v = stateTable[u].fail;
- while(v != -)
- {
- if(stateTable[v].nxt[i])
- {
- stateTable[stateTable[u].nxt[i]].fail = stateTable[v].nxt[i];
- // 在匹配fail指针的时候顺便更新cnt
- if(stateTable[stateTable[stateTable[u].nxt[i]].fail].cnt == )
- stateTable[stateTable[u].nxt[i]].cnt = ;
- break;
- }
- v = stateTable[v].fail;
- }
- if(v == -) stateTable[stateTable[u].nxt[i]].fail = ;
- }
- que.push(stateTable[u].nxt[i]);
- }
- /*****建立自动机nxt指针*****/
- else
- {
- if(u == ) stateTable[u].nxt[i] = ;
- else
- {
- int p = stateTable[u].fail;
- while(p != - && stateTable[p].nxt[i] == ) p = stateTable[p].fail;
- if(p == -) stateTable[u].nxt[i] = ;
- else stateTable[u].nxt[i] = stateTable[p].nxt[i];
- }
- }
- /*****建立自动机nxt指针*****/
- }
- }
- }
- matrix build_matrix()
- {
- matrix ans = matrix(size,size);
- for(int i=;i<size;i++)
- {
- for(int j=;j<;j++)
- {
- if(!stateTable[i].cnt && !stateTable[stateTable[i].nxt[j]].cnt)
- ans.e[i+][stateTable[i].nxt[j]+]++;
- }
- }
- return ans;
- }
- }aho;
- void print(matrix p)
- {
- int n = p.n;
- int m = p.m;
- for(int i=;i<=n;i++)
- {
- for(int j=;j<=m;j++)
- {
- printf("%d ",p.e[i][j]);
- }
- puts("");
- }
- }
- int main()
- {
- while(scanf("%d%d",&m,&n) == )
- {
- aho.init();
- char s[];
- for(int i=;i<=m;i++)
- {
- scanf("%s",s);
- aho.insert(s);
- }
- aho.build();
- matrix p = aho.build_matrix();
- p = solve(p,n);
- ull temp = ;
- for(int i=;i<=aho.size;i++) temp += p.e[][i];
- matrix t = matrix(,);
- t.e[][] = ;
- matrix A = matrix(,);
- A.e[][] = A.e[][] = ; A.e[][] = ;
- t = t * qpow(A,n);
- ull ans = t.e[][] - temp;
- printf("%llu\n",ans);
- }
- return ;
- }
最后觉得,,我之前矩阵模板里的print()真好用啊233= =。
HDU 2243 考研路茫茫――单词情结 ——(AC自动机+矩阵快速幂)的更多相关文章
- 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 ...
- hdu 2243 考研路茫茫——单词情结 AC自动机 矩阵幂次求和
题目链接 题意 给定\(N\)个词根,每个长度不超过\(5\). 问长度不超过\(L(L\lt 2^{31})\),只由小写字母组成的,至少包含一个词根的单词,一共可能有多少个? 思路 状态(AC自动 ...
- [hdu2243]考研路茫茫——单词情结(AC自动机+矩阵快速幂)
题意:长度不超过L,只由小写字母组成的,至少包含一个词根的单词,一共可能有多少个. 解题关键:利用补集转化的思想,先求一个词根也不包含的单词个数,然后用总的减去即可.长度不超过L需要用矩阵维数增加一倍 ...
- hdu 2243 考研路茫茫——单词情结(AC自动+矩阵)
考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- hdu_2243_考研路茫茫——单词情结(AC自动机+矩阵)
题目链接:hdu_2243_考研路茫茫——单词情结 题意: 让你求包含这些模式串并且长度不小于L的单词种类 题解: 这题是poj2788的升级版,没做过的强烈建议先做那题. 我们用poj2778的方法 ...
- HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵)
考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- HDU 2243 考研路茫茫——单词情结
考研路茫茫——单词情结 Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID ...
- HDU 2243 考研路茫茫——单词情结 求长度小于等于L的通路总数的方法
http://acm.hdu.edu.cn/showproblem.php?pid=2243 这是一题AC自动机 + 矩阵快速幂的题目, 首先知道总答案应该是26^1 + 26^2 + 26^3 .. ...
- HDU2243 考研路茫茫——单词情结 ——AC自动机、矩阵优化
题目链接:https://vjudge.net/problem/HDU-2243 考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others) Memor ...
随机推荐
- Sql Server根据字符串拆分多列
select parsename(REPLACE(Field,',','.'),3) as segment_1, parsename(REPLACE(Field,',','.'),2) as segm ...
- cookie和session,sessionStorage、localStorage和cookie的区别
1.cookie 含义: 存储在访问者的计算机中的变量,即存储在客户端 创建一个cookie /* getCookie方法判断document.cookie对象中是否存有cookie,若有则判断该co ...
- stm32位带
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bit ...
- EditText编辑框
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...
- DRDA
在谈到分布式DB2数据时,有必要谈谈DRDA. DRDA代表分布式关系数据库体系结构. 它是由IBM开发的一种体系结构,它使关系数据能够在多个平台之间分布. 平台和平台都可以相互通信. 例如,一个DB ...
- redis目录
一.redis基础 二.django-redis 三.redis数据操作详解 四.redis持久化
- 用js刷剑指offer(调整数组顺序使奇数位于偶数前面)
题目描述 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变. 牛客网链接 js代码 ...
- Petrozavodsk Winter Training Camp 2018 Jagiellonian U Contest Problem A. XOR
先把所有的数异或起来 得到sum 然后sum有一些位是1一些位是0 是0的位表示所有数里面有这位的数是偶数个 则无论怎么划分数 这一位对最终的答案都是不会有贡献的 因为偶数=偶数+偶数/奇数+奇数 ...
- java之高并发与多线程
进程和线程的区别和联系 从资源占用,切换效率,通信方式等方面解答 线程具有许多传统进程所具有的特征,故又称为轻型进程(Light—Weight Process)或进程元:而把传统的进程称为重型进程(H ...
- Nginx中ngx_http_proxy_module模块
该模块允许将请求传递给另⼀一台服务器器指令:1 ,proxy_pass设置代理理服务器器的协议和地址以及应映射位置的可选 URI .作为协议,可以指定“ http 或 https .可以将地址指定为域 ...