HDU 2243 考研路茫茫——单词情结 ( Trie图 && DP && 矩阵构造幂和 )
题意 : 长度不超过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。
分析 : 这题和 POJ 2778 非常相似,如果没有做过 POJ 2778 建议先去搞定那道题。此题难点就在于这个是要求不超过 L 长度包含词根的单词,根据解决 POJ 2778 的经验,我们可以得出 答案 = 总单词种类数 - 不包含词根的单词数。首先总单词数可以很容易想到为 261 + 262 + 263 + ..... + 26L ,而不包含词根的单词总数可以这样得到 ==> 假设原 Trie 图构建出来的状态矩阵为 A ,那么同样的我们需要构造一个幂和即 A1 + A2 + A3 + ..... + AL 然后最后的答案便是 ∑AL(0, i) ( i ∈ 1~矩阵长度 ) ,那怎么去构造这两个幂和呢?

只要利用这个公式即可,用原矩阵 + 单位矩阵 + 零矩阵构造出新矩阵,最后右上角的矩阵便是幂和的矩阵!
这里还有一点要注意,就是对于 2^64次方求模有一个很巧的方法,也就是直接定义为 unsigned long long (范围 : 0 ~ 2^64 -1),溢出就相当于求模了!
#include<string.h>
#include<stdio.h>
#include<iostream>
#include<queue>
#define ULL unsigned long long
using namespace std;
;
;
int maxn;///矩阵的大小
];
][]; }unit, M;
mat operator * (mat a, mat b){
mat ret;
; i<maxn; i++){
; j<maxn; j++){
ret.m[i][j] = (ULL);
; k<maxn; k++){
ret.m[i][j] += a.m[i][k]*b.m[k][j];
}
}
}
return ret;
}
inline void init_unit() {
; i<maxn; i++)
unit.m[i][i] = ;
}
mat pow_mat(mat a, long long n){
mat ret = unit;
while(n){
) ret = ret * a;
a = a*a;
n >>= ;
}
return ret;
}
struct Aho{
struct StateTable{
int Next[Letter];
int fail, flag;
}Node[Max_Tot];
int Size;
queue<int> que;
inline void init(){
while(!que.empty()) que.pop();
memset(Node[].Next, , ].Next));
Node[].fail = Node[].flag = ;
Size = ;
}
inline void insert(char *s){
;
; s[i]; i++){
int idx = s[i] - 'a';
if(!Node[now].Next[idx]){
memset(Node[Size].Next, , sizeof(Node[Size].Next));
Node[Size].fail = Node[Size].flag = ;
Node[now].Next[idx] = Size++;
}
now = Node[now].Next[idx];
}
Node[now].flag = ;
}
inline void BuildFail(){
Node[].fail = -;
; i<Letter; i++){
].Next[i]){
Node[Node[].Next[i]].fail = ;
que.push(Node[].Next[i]);
}].Next[i] = ;///必定指向根节点
}
while(!que.empty()){
int top = que.front(); que.pop();
;
; i<Letter; i++){
int &v = Node[top].Next[i];
if(v){
que.push(v);
Node[v].fail = Node[Node[top].fail].Next[i];
}else v = Node[Node[top].fail].Next[i];
}
}
}
inline void BuildMatrix(){
; i<Size; i++)
; j<Size; j++)
M.m[i][j] = ;
; i<Size; i++){
; j<Letter; j++){
if(!Node[i].flag && !Node[ Node[i].Next[j] ].flag)
M.m[i][Node[i].Next[j]]++;
}
}
maxn = Size;
}
}ac;
ULL GetSum(long long num){
mat ret;
ret.m[][] = ;
ret.m[][] = ;
ret.m[][] = ;
ret.m[][] = ;
int tmp = maxn;
maxn = ;
ret = pow_mat(ret, ++num);
maxn = tmp;
][]-;
}
ULL GetElimination(long long num){
mat tmp;
; i<maxn; i++)///左上角 为 原矩阵
; j<maxn; j++)
tmp.m[i][j] = M.m[i][j];
; i<maxn; i++)///右上角 为 单位矩阵
); j++)
tmp.m[i][j] = (i+maxn == j);
); i++)///左下角 为 零矩阵
; j<maxn; j++)
tmp.m[i][j] = ;
); i++)///右下角 为 单位矩阵
); j++)
tmp.m[i][j] = (i==j);
int Temp = maxn;
maxn <<= ;///先将原本矩阵的大小放大一倍进行快速幂运算,这个和我快速幂的写法有关
tmp = pow_mat(tmp, ++num);
ULL ret = (ULL);
maxn = Temp;///再回复成原来大小
); i++)///右上角的矩阵就是幂和了
ret += tmp.m[][i];
return (--ret);///需要 -1
}
int main(void)
{
int n, m;
while(~scanf("%d %d", &m, &n)){
ac.init();
; i<m; i++){
scanf("%s", S);
ac.insert(S);
}
ac.BuildFail();
ac.BuildMatrix();
init_unit();
ULL Tot = GetSum((long long)n);///注意是传long long不然会爆int
ULL Elimination = GetElimination((long long)n);
cout<<Tot-Elimination<<endl;
}
;
}
HDU 2243 考研路茫茫——单词情结 ( Trie图 && DP && 矩阵构造幂和 )的更多相关文章
- HDU 2243考研路茫茫——单词情结 (AC自动机+矩阵快速幂)
背单词,始终是复习英语的重要环节.在荒废了3年大学生涯后,Lele也终于要开始背单词了. 一天,Lele在某本单词书上看到了一个根据词根来背单词的方法.比如"ab",放在单词前一般 ...
- HDU 2243 考研路茫茫――单词情结 ——(AC自动机+矩阵快速幂)
和前几天做的AC自动机类似. 思路简单但是代码200余行.. 假设solve_sub(i)表示长度为i的不含危险单词的总数. 最终答案为用总数(26^1+26^2+...+26^n)减去(solve_ ...
- HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)
http://acm.hdu.edu.cn/showproblem.php?pid=2243 题意: 给出m个模式串,求长度不超过n的且至少包含一个模式串的字符串个数. 思路: 如果做过poj2778 ...
- HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵)
考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- HDU 2243 考研路茫茫——单词情结(AC自动机+DP+快速幂)
题目链接 错的上头了... 这题是DNA的加强版,26^1 +26^2... - A^1-A^2... 先去学了矩阵的等比数列求和,学的是第二种方法,扩大矩阵的方法.剩下就是各种模板,各种套. #in ...
- 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 考研路茫茫——单词情结 ac自动机+矩阵快速幂
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2243 题意:给定N(1<= N < 6)个长度不超过5的词根,问长度不超过L(L <23 ...
- HDU 2243 考研路茫茫——单词情结 求长度小于等于L的通路总数的方法
http://acm.hdu.edu.cn/showproblem.php?pid=2243 这是一题AC自动机 + 矩阵快速幂的题目, 首先知道总答案应该是26^1 + 26^2 + 26^3 .. ...
随机推荐
- 在GAE中用Python编写webapp进行Post数据采集
#!/usr/bin/env python # -*- coding: cp936 -*- # # Copyright 2007 Google Inc. # # Licensed under the ...
- excel 导入导出测试点
目前,为方便操作,很多系统都会增加批量导入导出的功能.文件导入导出一般格式都是excel.由于用户直接在excel在填写内容,无法控制填写的格 式,加上excel解析比较困难,所以一般涉及到excel ...
- js 自调函数
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- springboot + mybaits + oracle 项目
1.pom设置 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="htt ...
- 基于webstorm卡顿问题的2种解决方法
基于webstorm卡顿问题的2种解决方法:https://www.jb51.net/article/128441.htm
- mock.js的运用
一:概念 Mock.js是一款模拟数据生成器,旨在帮助前端攻城师独立于后端进行开发,帮助编写单元测试.提供了以下模拟功能: 根据数据模板生成模拟数据 模拟 Ajax 请求,生成并返回模拟数据 基于 H ...
- 由于;引发的Oracle的BadSqlExecption
一.在使用单引号进行各种转换合并的时候发生的异常: 1:首先单引号的表示符为 ' 在Oracle中如果SQL语句带上了分号是会报错的, 在SQL传入进行执行的时候会报BadSQLExecption,这 ...
- ARM之cache
一. 什么是cache 1.1. cache简介 a. Cache 即高速缓冲存储器,是位于 CPU 与内存之间的高速存储器,它的容量比内存小但交换速度快. b. ARM处理器的主频为上百M甚至几G, ...
- java中的四种引用方式(强引用,软引用,弱引用,虚引用)
java内存管理主要有内存分配和内存回收,都不需要程序员负责,垃圾回收的机制主要是看对象是否有引用指向该对象. java中对象的引用主要有四种:强引用,软引用,弱引用,虚引用. Java中提供这四种引 ...
- jquery data的用法
jquery data和 jquery attr, js getAttribute 有着本质的区别,并且无法用$(el).data('property')的方法,去获取$(el).attr('data ...