题意:长度不超过L,只由小写字母组成的,至少包含一个词根的单词,一共可能有多少个。

解题关键:利用补集转化的思想,先求一个词根也不包含的单词个数,然后用总的减去即可。长度不超过L需要用矩阵维数增加一倍来处理前缀和。

这里还有第二种考虑思路,只增加一维,自己写一个三维矩阵验证一下即可,最后一列每一行代表每一行的前缀和。

方法1:

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
typedef unsigned long long ll;
const int N=;
const int MAXN=;
struct mat{
ll m[][];
};
ll m,n;
struct Trie{
int Next[MAXN][N],Fail[MAXN],root,tot;
bool End[MAXN];
int newnode(){
for(int i=;i<N;i++) Next[tot][i]=-;
End[tot++]=false;
return tot-;
}
void init(){
tot=;
root=newnode();
}
void insert(char buf[]){
int len=strlen(buf),now=root,k;
for(int i=;i<len;i++){
k=buf[i]-'a';
if(Next[now][k]==-) Next[now][k]=newnode();
now=Next[now][k];
}
End[now]=true;
}
void build(){
queue<int>que;
Fail[root]=root;
for(int i=;i<N;i++){
if(Next[root][i]==-) Next[root][i]=root;
else{
Fail[Next[root][i]]=root;
que.push(Next[root][i]);
}
}
while(!que.empty()){
int now=que.front();
que.pop();
if(End[Fail[now]]) End[now]=true;
for(int i=;i<N;i++){
if(Next[now][i]==-) Next[now][i]=Next[Fail[now]][i];
else{
Fail[Next[now][i]]=Next[Fail[now]][i];
que.push(Next[now][i]);
}
}
}
}
mat get_mat(){
mat B={};
for(int i=;i<tot;i++){
if(End[i]) continue;
for(int j=;j<N;j++){
if(End[Next[i][j]]==false) B.m[i][Next[i][j]]++;//不能直接置1
}
}
for(int i=;i<tot;i++){
B.m[i+tot][i]=B.m[i+tot][i+tot]=;
}
return B;
}
}; mat mul(mat &A,mat &B,int len){
mat C={};
for(int i=;i<len;i++){
for(int j=;j<len;j++){
for(int k=;k<len;k++){
C.m[i][j]+=A.m[i][k]*B.m[k][j];
}
}
}
return C;
} mat pow(mat A,ll n,int len){
mat B={};
for(int i=;i<len;i++) B.m[i][i]=;
while(n){
if(n&) B=mul(B,A,len);
A=mul(A,A,len);
n>>=;
}
return B;
} Trie ac;
char buf[];
int main(){
while(scanf("%llu%llu",&m,&n)!=EOF){
ac.init();
for(int i=;i<m;i++){
scanf("%s",buf);
ac.insert(buf);
}
ac.build();
mat B=ac.get_mat();
B=pow(B,n+,*ac.tot);
mat C={},D={},E={};
for(int i=;i<ac.tot;i++) C.m[i][i]=;
D=mul(B,C,*ac.tot);
E.m[][]=,E.m[][]=,E.m[][]=E.m[][]=;
E=pow(E,n+,);
ll res1=,res2=E.m[][];
for(int i=;i<ac.tot;i++){
if(i==) D.m[ac.tot][i]-=;
res1+=D.m[ac.tot][i];
}
printf("%llu\n",res2--res1);
}
return ;
}

法2:

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
typedef unsigned long long ll;
const int N=;
const int MAXN=;
struct mat{
ll m[][];
};
ll m,n;
struct Trie{
int Next[MAXN][N],Fail[MAXN],root,tot;
bool End[MAXN];
int newnode(){
for(int i=;i<N;i++) Next[tot][i]=-;
End[tot++]=false;
return tot-;
}
void init(){
tot=;
root=newnode();
}
void insert(char buf[]){
int len=strlen(buf),now=root,k;
for(int i=;i<len;i++){
k=buf[i]-'a';
if(Next[now][k]==-) Next[now][k]=newnode();
now=Next[now][k];
}
End[now]=true;
}
void build(){
queue<int>que;
Fail[root]=root;
for(int i=;i<N;i++){
if(Next[root][i]==-) Next[root][i]=root;
else{
Fail[Next[root][i]]=root;
que.push(Next[root][i]);
}
}
while(!que.empty()){
int now=que.front();
que.pop();
if(End[Fail[now]]) End[now]=true;
for(int i=;i<N;i++){
if(Next[now][i]==-) Next[now][i]=Next[Fail[now]][i];
else{
Fail[Next[now][i]]=Next[Fail[now]][i];
que.push(Next[now][i]);
}
}
}
}
mat get_mat(){
mat B={};
for(int i=;i<=tot;i++) B.m[i][tot]=;
for(int i=;i<tot;i++){
if(End[i]) continue;
for(int j=;j<N;j++){
if(End[Next[i][j]]==false) B.m[i][Next[i][j]]++;//不能直接置1
}
}
return B;
}
}; mat mul(mat &A,mat &B,int len){
mat C={};
for(int i=;i<len+;i++){
for(int j=;j<len+;j++){
for(int k=;k<len+;k++){
C.m[i][j]+=A.m[i][k]*B.m[k][j];
}
}
}
return C;
} mat pow(mat A,ll n,int len){
mat B={};
for(int i=;i<len;i++) B.m[i][i]=;
while(n){
if(n&) B=mul(B,A,len);
A=mul(A,A,len);
n>>=;
}
return B;
} Trie ac;
char buf[];
int main(){
while(scanf("%llu%llu",&m,&n)!=EOF){
ac.init();
for(int i=;i<m;i++){
scanf("%s",buf);
ac.insert(buf);
}
ac.build();
mat B=ac.get_mat(); ll res1,res2;
B=pow(B,n+,ac.tot);
res1=B.m[][ac.tot]-; mat E={};
E.m[][]=,E.m[][]=,E.m[][]=E.m[][]=;
E=pow(E,n+,);
res2=E.m[][]; printf("%llu\n",res2--res1);
}
return ;
}

[hdu2243]考研路茫茫——单词情结(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自动机+DP+快速幂)

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

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

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

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

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

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

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

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

    题目大意:给n个单词,长度不超过L的单词有多少个包含n个单词中的至少一个单词. 题目分析:用长度不超过L的单词书目减去长度在L之内所有不包含任何一个单词的书目. 代码如下: # include< ...

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

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

  8. hdu2243 考研路茫茫——单词情结【AC自动机】【矩阵快速幂】

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

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

    与POJ2778一样.这题是求长度不超过n且包含至少一个词根的单词总数. 长度不超过n的单词总数记为Sn,长度不超过n不包含词根的单词总数记为Tn. 答案就是,Sn-Tn. Sn=26+262+263 ...

随机推荐

  1. HDU 1698 Just a Hook(线段树区间替换)

    题目地址:pid=1698">HDU 1698 区间替换裸题.相同利用lazy延迟标记数组,这里仅仅是当lazy下放的时候把以下的lazy也所有改成lazy就好了. 代码例如以下: # ...

  2. Jenkins系列之-—08 实现SQL脚本批量执行

    公司内部推广DevOps,所有目前在维护阶段和开发阶段项目全部配置上了自动发布.采用Jenkins+SVN+ANT,之后批量执行SQL语句的实现提上日程 一.环境 Linux环境 安装ANT工具,且下 ...

  3. iLBC简要介绍

    iLBC(internet lowbitrate codec):是全球著名语音引擎提供商Global IP Sound开发,它是低比特率的编码解码器,提供在丢包时具有的强大的健壮性.iLBC 提供的语 ...

  4. ScrollView滑动的监听

    ScrollView滑动的监听 有时候我们须要监听ScrollView的滑动事件.来完毕业务需求. 第一种: 能够直接实现OnTouchListener接口.在这里面写你所须要的操作 scrollVi ...

  5. java 连接mysql 和sql server2008代码

    这两天用java分别连接mysql和sql server2008代码.刚開始都是有错.如今找到了在 自己机器上成功连接的代码: 1. mysql Class.forName("com.mys ...

  6. git 下载与Linux源码安装最新版

    win: https://git-for-windows.github.io/ 或 https://git-scm.com/downloads   官网!   源码安装git Git 的工作需要调用  ...

  7. ACM-BFS之Open the Lock——hdu1195(双向BFS)

    这道题的0基础版本号,暴力BFS及题目详情请戳:http://blog.csdn.net/lttree/article/details/24658031 上回书说道,要用双向BFS来尝试一下. 最终A ...

  8. Eclipse-----Eclipse断点调试

  9. android启动另一应用

    http://www.2cto.com/kf/201203/122910.html Android SDK中有这样一个API: public abstract Intent getLaunchInte ...

  10. .Net——实现IConfigurationSectionHandler接口定义处理程序处理自定义节点

    除了使用.net里面提供的内置处理程序来处理我们的自定义节点外,我们还可以通过多种方法,来自己定义处理类处理我们的自定义节点,本文主要介绍通过实现IConfigurationSectionHandle ...