题目链接:点击查看

题目大意:给出 n 个词根,现在要求出长度不大于 len 的单词中,有多少单词包含至少一个词根

题目分析:如果我们反过来想,也就是求出来总的单词数,然后减去不包含词根的单词数,剩下的就是本题的答案了,不包含词根的单词数可以用AC自动机+矩阵保存转移状态,然后矩阵快速幂求出,但是这个题目需要求的是不大于 len 的单词数,所以需要给矩阵多增加一维,具体做法可以参考这个博客:

https://blog.csdn.net/baidu_23081367/article/details/52347256

我感觉讲的非常不错,很巧妙的求出A^0+A^1+A^2....+A^N,这里的A可以是数字,也可以是矩阵,这样的话我们就能很轻松的解决这个问题了,顺便用了一下上面博主的矩阵模板,不得不说非常好用

对于所有的单词总数,显然是26^0+26^1+....26^n,我们可以构造方程F(n)为到n为止的平方和,可以得出转移方程为:

F( n ) = F( n - 1 ) * 26 + 26

然后构造矩阵转移就好了

不过最后求出来的答案不知道为什么总是少 1,加上 1 就AC了

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=50;char s[N];int fail[N],trie[N][26],cnt;bool vis[N];const int mat_size = 40 * 2;//矩阵大小,需要乘以2,为了&运算的时候需要二倍的矩阵大小struct Matrix
{unsigned long long a[mat_size][mat_size];int x, y;//长宽Matrix() //返回0矩阵{memset(a,0,sizeof(a));}Matrix(int x,int y)//返回0矩阵,并且x,y赋值{this->x = x;this->y = y;memset(a, 0,sizeof(a));}Matrix(int n)  //返回n*n的【单位矩阵】{this->x=n;this->y=n;memset(a,0,sizeof(a));for (int i = 0; i <n;++i)    a[i][i]=1;}Matrix operator * (const Matrix &B)//矩阵乘法{Matrix tmp;for (int i = 0; i < x; ++ i)for (int j = 0; j < B.y; ++ j){tmp.a[i][j] = 0;for (int k = 0; k < y; ++ k){tmp.a[i][j] = (tmp.a[i][j] + a[i][k] * B.a[k][j]);}}tmp.x = x;tmp.y=B.y;return tmp;}Matrix operator ^ (int b)//矩阵A的b次方{Matrix ret = Matrix(x);  Matrix A = *this;while( b )  {  if( b & 1 )   ret = ret * A ;  b >>= 1 ;  A = A * A ;  }  return ret ;  }Matrix operator & (int b)//A^0 + A^1+A^2+A^3+++A^n,其中A是矩阵。最后返回的就是一个矩阵{Matrix ret = *this;for (int i = ret.x; i < ret.x * 2; ++ i)   {ret.a[i-ret.x][i]= 1;ret.a[i][i] = 1;}ret.x <<= 1;ret.y <<= 1;//pg(ret);ret = ret^b;ret.x >>= 1;ret.y >>= 1;for (int i = 0; i < ret.x; ++ i)  for (int j = 0; j < ret.y; ++ j)ret.a[i][j] += ret.a[i][j + ret.x];return ret;}void pg(Matrix A){for (int i = 0; i <A.x; ++i){for (int j = 0; j < A.y;++j) cout<<A.a[i][j]<<" ";cout<<endl;}cout<<endl;}
};void getmaze(Matrix &maze)
{maze.x=maze.y=cnt+1;for(int i=0;i<=cnt;i++)if(!vis[i])for(int j=0;j<26;j++)if(!vis[trie[i][j]])maze.a[i][trie[i][j]]++;
}void insert_word()
{int len=strlen(s);int pos=0;for(int i=0;i<len;i++){int to=s[i]-'a';if(!trie[pos][to])trie[pos][to]=++cnt;pos=trie[pos][to];}vis[pos]=true;
}void getfail()
{queue<int>q;for(int i=0;i<26;i++){if(trie[0][i]){fail[trie[0][i]]=0;q.push(trie[0][i]);}}while(!q.empty()){int cur=q.front();q.pop();for(int i=0;i<26;i++){if(trie[cur][i]){fail[trie[cur][i]]=trie[fail[cur]][i];q.push(trie[cur][i]);}elsetrie[cur][i]=trie[fail[cur]][i];vis[trie[cur][i]]|=vis[trie[fail[cur]][i]];}}
}void init()
{cnt=0;memset(vis,false,sizeof(vis));memset(trie,0,sizeof(trie));
}int main()
{
//#ifndef ONLINE_JUDGE
//  freopen("input.txt","r",stdin);
//#endif
//  ios::sync_with_stdio(false);int n,m;while(scanf("%d%d",&n,&m)!=EOF){init();while(n--){scanf("%s",s);insert_word();}getfail();Matrix maze;getmaze(maze);maze=maze&m;ull ans=0;for(int i=0;i<=cnt;i++)ans-=maze.a[0][i];   maze.x=maze.y=2;maze.a[0][0]=maze.a[1][0]=26;maze.a[0][1]=0;maze.a[1][1]=1;maze=maze^m;ans+=maze.a[1][0];cout<<ans+1<<endl;}return 0;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

最新文章

  1. Oracle分析函数入门
  2. 批处理删除编译产生的多余文件
  3. vue 改变domclass_手机上的大片制作软件——如何使用VUE
  4. (2021) 20 [虚拟化] 进程调度
  5. TypeError object of type ‘type‘ has no len()—Python报错问题:
  6. 服务器怎么修改密码_亚马逊账号登陆不上,修改密码后遭冻结怎么办?有没有什么申诉的办法?...
  7. 苹果CMSV10绿色毛毛虫主题模板
  8. Linux下的touch命令
  9. Rafy 框架 - 为数据库生成注释
  10. Windows Server 2003 系统安装
  11. 一文看懂BGP路由黑洞问题
  12. ESP32-CAM 摄像头学习
  13. K3 LEDE踩坑专题
  14. 【压力测试】用JMeter进行百科网站压力测试
  15. 中国在计算机领域取得的成就,厉害了我的国——盘点中国科学近年有哪些成就...
  16. 蓝桥杯 历届试题 史丰收速算
  17. 环签名原理与隐私保护
  18. 关于D3D中AGP显存,内存,显存三种内存的解释
  19. 读书笔记--高效能人士的七个习惯+执行4原则
  20. 交易员怎样于牛市中基于KDJ进行选股

热门文章

  1. 编写python程序、计算账户余额_小明有20w存款存在余额宝中,按余额宝年收益为3.35%计算,用Python编写程序计算,多少年后小明的存款达到30w?...
  2. realmeq参数配置详情_小米11什么时候发布 小米11参数配置详情
  3. Jar包部署-设置打包方式为jar
  4. DelayExchange原理
  5. Nginx的Gzip和sendfile的共存问题
  6. 使用Nginx代理和转发Websocket连接
  7. MyBatis 插件原理与自定义插件-应用场景分析
  8. TCP/IP协议的SYN攻击
  9. Spring Framework总览面试题精选
  10. MapReduce运行机制-Map阶段