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

杭电OJ 题目地址

【题意】

单词和词根仅由小写字母组成。给定N个词根,求长度不超过L 且至少包含一个词根的单词可能有多少个?

若有两个词根aa和ab,则长度不超过3且至少包含一个词根的单词可能存在104个:aa, ab(两个)、aaa, aab, aac…aaz(26个)、aba, abb,abc…abz(26个)、baa, caa, daa…zaa(25个)、bab, cab, dab…zab(25个)。

【输入输出】

输入:

包含多个测试用例。每个测试用例都占两行。第1行有两个正整数N 和L (0<N <6,0<L <231 )。第2行有N 个词根,每个词根的长度都不超过5。

输出:

对每个测试用例,都单行输出满足条件的单词总数mod 264的值。

【样例】

【思路分析】

本题求解长度不超过L 且至少包含一个词根的单词可能共计多少个。

这道题和 POJ2778有两处不同。

  • 本题中长度不超过L ;POJ2778中长度为n。
  • 本题求解的是至少包含一个词根的单词数,POJ2778求解的是不包含遗传病片段的DNA序列数。

【算法设计】

① 求解由26个小写字母组成且长度不超过L 的单词数ans。

② 求解长度不超过L 且不包含词根的单词数res。

③ 长度不超过L 且至少包含一个词根的单词数为两者之差ansres。

【举个栗子】

① 长度不超过L 的单词数

长度不超过L 的单词包括长度为1的26个、长度为2的26^2 个……长度为L 的26^ L 个,其和值26+26^2 +…+26^L 为长度不超过L 的单词数,如何计算呢?

对等比矩阵求和有经典算法,假定原矩阵为 A ,阶数为n ,则构造一个阶数为2n 的矩阵,其中0代表0矩阵, E 代表单位矩阵:

|A E|
|0 E|

求出的K 次矩阵的右上n 子矩阵正好是等比矩阵的K 项和。

求出矩阵的n 次幂的第1行之和减1,即可得到ans=26^1 +26^2 +…+26^(n -1) +26^n ,因为mod 2^64 ,所以直接用unsigned long long就可以了,系统会自动截断,相当于取模运算。

② 长度不超过L 且不包含词根的单词数

现在求解不超过L 且不包含词根的单词数,需要将所有长度小于或等于L 且不包含词根的单词数累加。要实现累加结果,只需在矩阵最后一行添加0,在最后一列添加1即可。

根据输入样例1的词根{aa ab}构建AC自动机,如下图所示。


不包含词根的原矩阵如下:

25 1
24 0

为实现累加效果,在原矩阵的最后一行添加0且在最后一列添加1,单位矩阵变为:

25 1 1
24 0 1
0  0 1

若M [i , j ]表示从节点i 到j 只走1步有几种走法,则 M 的n 次幂表示从节点i 到j 走n 步有几种走法。求出矩阵的n 次幂第1行之和减1,得到长度不超过L 且不包含词根的单词数res。

③ 长度不超过L 且至少包含一个词根的单词数

长度不超过L 且至少包含一个词根的单词数为两者之差ans-res。

【算法实现】

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>using namespace std;typedef unsigned long long ll;const int maxn=40;
const int K=26;
int root,L;struct mat{ll a[maxn][maxn];int n;mat(int _n){n=_n;memset(a,0,sizeof(a));}
};mat mul(mat A,mat B){//矩阵乘法mat C(A.n);for(int i=0;i<A.n;i++)for(int j=0;j<B.n;j++)for(int k=0;k<A.n;k++)C.a[i][j]+=A.a[i][k]*B.a[k][j];return C;
}mat pow(mat A,int n){//A^nmat ans(A.n);for(int i=0;i<A.n;i++)ans.a[i][i]=1;//单位矩阵 while(n>0){if(n&1)ans=mul(ans,A);A=mul(A,A);n>>=1;}return ans;
}struct ACAutomata{int next[maxn][K],fail[maxn],end[maxn],id[maxn];int newNode(){//新建结点for(int i=0;i<K;i++)next[L][i]=-1;end[L]=0;return L++;}void init(){//初始化L=0;root=newNode();}void insert(char s[]){//插入一个结点int len=strlen(s);int p=root;for (int i=0;i<len;i++){int ch=s[i]-'a';if(next[p][ch]==-1)next[p][ch]=newNode();p=next[p][ch];}end[p]++;}void build(){//构建AC自动机queue<int> Q;fail[root]=root;for (int i=0;i<K;i++){if(next[root][i]==-1){next[root][i]=root;}else{fail[next[root][i]]=root;Q.push(next[root][i]);}}while(Q.size()){int now=Q.front();Q.pop();if(end[fail[now]])end[now]++;//重要!!如果当前结点的失败指针end有结束标记,当前结点的end++ for(int i=0;i<K;i++){if (next[now][i]!=-1){fail[next[now][i]]=next[fail[now]][i];Q.push(next[now][i]);}elsenext[now][i]=next[fail[now]][i];}}}ll query(int n){int ids=0;memset(id,-1,sizeof(id));for(int i=0;i<L;i++)//对未标记的结点重新编号 if(!end[i])id[i]=ids++;mat F(ids+1);      for(int u=0;u<L;u++){if(end[u]) continue;for(int j=0;j<K;j++){int v=next[u][j];if(!end[v])F.a[id[u]][id[v]]++;}}for(int i=0;i<ids+1;i++)F.a[i][ids]=1;F=pow(F,n);ll res=0;for(int i=0;i<L;i++)res+=F.a[0][i];return --res;}
}ac;ll pow_2(int n){//求26+26^2+...+26^nmat C(2);C.a[0][0]=26;C.a[0][1]=C.a[1][1]=1;C=pow(C,n);ll ans=C.a[0][0]+C.a[0][1];return --ans;
}int main(){int m,n;char str[20];while(~scanf("%d%d",&m,&n)){ac.init();while (m--){scanf("%s",str);ac.insert(str);}ac.build();cout<<pow_2(n)-ac.query(n)<<endl;}return 0;
}

【HDU No. 2243】单词情结 考研路茫茫——单词情结相关推荐

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  9. hdu2243考研路茫茫——单词情结

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

最新文章

  1. 图解梯度下降背后的数学原理
  2. pthreads v3在centos7下的安装与配置
  3. 2.安装Ubuntu系统时,系统时间显示不对
  4. 微软亚洲研究院等提出CNN训练新方法RePr,准确率显著提升
  5. 第八篇、盒子模型和距中的设置方法
  6. struts2文件下载出现Can not find a java.io.InputStream with the name的错误
  7. 客户端证书错误避坑指南
  8. 1070. 结绳(25)
  9. 增量式pid调节方式有何优点_PID控制算法
  10. Docker快速安装Sybase数据库DBeaver数据库图形化管理开发工具
  11. java提取(获取)博客信息(内容)
  12. Sophix介绍与实践
  13. U盘/移动硬盘的文件夹自动分类怎么消除
  14. mysql8 启动报错:Error while setting value ‘STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DI
  15. NextCloud如何共享文件
  16. java用线程做小球碰撞_多线程之碰撞小球
  17. oracle 自动备份压缩(windows下)
  18. hp 打印机更改 wifi direct 的密码
  19. JAVA爬虫-上海公交线路爬取
  20. 03-Java核心类库_设计模式【未完待续】

热门文章

  1. weblogic unable to get file lock问题解决方案
  2. 【喜讯】PerfMa再获高瓴创投领投1.5亿A++轮融资
  3. 科研萌新成长记17——落地
  4. WZOI-272友谊
  5. solidworks2014可否保存成以前版本?--问题解决
  6. 结婚吉日怎样挑选?好好把握幸福启程
  7. python中num函数是什么意思_如何理解python3函数中num的用法?
  8. vhosts.conf域名配置
  9. 基于SSM的植物花草养护交流网站设计
  10. 给众多IT行业开发者的一个建议,要注意避开黑心的培训机构