AC自动机+矩阵(构造字符串 好)hdu2243
来源:互联网 发布:sqlserver新连接一个库 编辑:程序博客网 时间:2024/06/05 08:27
Online JudgeOnline ExerciseOnline TeachingOnline ContestsExercise AuthorF.A.Q
Hand In Hand
Online Acmers
Forum | Discuss
Statistical ChartsBest Coder beta
VIP | STD Contests
Virtual Contests
DIY | Web-DIY beta
Recent Contests
Total Submission(s): 3567 Accepted Submission(s): 1030
Hand In Hand
Online Acmers
Forum | Discuss
Statistical ChartsBest Coder beta
VIP | STD Contests
Virtual Contests
DIY | Web-DIY beta
Recent Contests
lee
Mail 0(0)
Control Panel
Sign Out
Mail 0(0)
Control Panel
Sign Out
BestCoder官方QQ群:385386683 欢迎加入~
寻人启事:2014级新生看过来!考研路茫茫——单词情结
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3567 Accepted Submission(s): 1030
Problem Description
背单词,始终是复习英语的重要环节。在荒废了3年大学生涯后,Lele也终于要开始背单词了。
一天,Lele在某本单词书上看到了一个根据词根来背单词的方法。比如"ab",放在单词前一般表示"相反,变坏,离去"等。
于是Lele想,如果背了N个词根,那这些词根到底会不会在单词里出现呢。更确切的描述是:长度不超过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。
这个只是很小的情况。而对于其他复杂点的情况,Lele实在是数不出来了,现在就请你帮帮他。
一天,Lele在某本单词书上看到了一个根据词根来背单词的方法。比如"ab",放在单词前一般表示"相反,变坏,离去"等。
于是Lele想,如果背了N个词根,那这些词根到底会不会在单词里出现呢。更确切的描述是:长度不超过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。
这个只是很小的情况。而对于其他复杂点的情况,Lele实在是数不出来了,现在就请你帮帮他。
Input
本题目包含多组数据,请处理到文件结束。
每组数据占两行。
第一行有两个正整数N和L。(0<N<6,0<L<2^31)
第二行有N个词根,每个词根仅由小写字母组成,长度不超过5。两个词根中间用一个空格分隔开。
每组数据占两行。
第一行有两个正整数N和L。(0<N<6,0<L<2^31)
第二行有N个词根,每个词根仅由小写字母组成,长度不超过5。两个词根中间用一个空格分隔开。
Output
对于每组数据,请在一行里输出一共可能的单词数目。
由于结果可能非常巨大,你只需要输出单词总数模2^64的值。
由于结果可能非常巨大,你只需要输出单词总数模2^64的值。
Sample Input
2 3aa ab1 2a
Sample Output
10452
题意:求长度最多为L并且至少包含一个给出字符串的有多少个
思路:这个题跟poj2778基本一样,我们只需要先求出不包含的有多少个,然后用总的去减就可以得到结果
需要注意的:
1.因为要求长度不大于L的,所以相当于求A+A^2+A^3+...+A^L,这个有三种方法
a.可以用倍增法,二分求解
b.|A 1| |A^n 1+A+A^2+A^3+...+A^(n-1)|
|0 1|的n次方为 |0 1|
c.这个方法刚开始没太看懂,自己摸你一下就知道了
|a1 a2 1|
|a3 a4 1|
|0 0 1|的N次方的和就是1+A+A^2+A^3+...+A^n的元素的和
2.2^64取模,直接定义成unsigned long long截取就行了
a方法:
#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<algorithm>using namespace std;typedef unsigned long long LL;const int maxn=50;const int SIGMA_SIZE=26;int N,L;char s[20];struct Matrix{ LL mat[30][30]; int n; Matrix(int x) { memset(mat,0,sizeof(mat)); n=x; } Matrix(){} Matrix operator*(Matrix a) { Matrix res(n); for(int k=0;k<n;k++) { for(int i=0;i<n;i++) { if(mat[i][k]==0)continue; for(int j=0;j<n;j++) { //if(a.mat[j][k]==0)continue; res.mat[i][j]=(res.mat[i][j]+mat[i][k]*a.mat[k][j]); } } } return res; } Matrix operator+(Matrix A) { Matrix res(A.n); for(int i=0;i<n;i++) for(int j=0;j<n;j++) res.mat[i][j]=(mat[i][j]+A.mat[i][j]); return res; }};Matrix A;Matrix pow_mul(Matrix A,LL x){ Matrix res(A.n); for(int i=0;i<=res.n;i++)res.mat[i][i]=1; while(x) { if(x&1)res=res*A; A=A*A; x>>=1; } return res;}Matrix pow_sum(LL x){ if(x==1)return A; Matrix tmp=pow_sum(x/2); Matrix sum=(tmp+pow_mul(A,x/2)*tmp); if(x&1)sum=(sum+pow_mul(A,x)); return sum;}struct AC{ int ch[maxn][26],val[maxn]; int fail[maxn],last[maxn]; int sz; void clear(){memset(ch[0],0,sizeof(ch[0]));sz=1;} int idx(char x){return x-'a';} void insert(char *s) { int n=strlen(s); int u=0; for(int i=0;i<n;i++) { int c=idx(s[i]); if(!ch[u][c]) { memset(ch[sz],0,sizeof(ch[sz])); val[sz]=0; ch[u][c]=sz++; } u=ch[u][c]; } val[u]=1; } void getfail() { queue<int> q; fail[0]=0; int u=0; for(int i=0;i<SIGMA_SIZE;i++) { u=ch[0][i]; if(u){fail[u]=last[u]=0;q.push(u);} } while(!q.empty()) { int r=q.front();q.pop(); if(val[fail[r]])val[r]=1; for(int c=0;c<SIGMA_SIZE;c++) { u=ch[r][c]; if(!u){ch[r][c]=ch[fail[r]][c];continue;} q.push(u); int v=fail[r]; while(v&&!ch[v][c])v=fail[v]; fail[u]=ch[v][c]; last[u]=val[fail[u]]?fail[u]:last[fail[u]]; } } } Matrix getMatrix() { Matrix res(sz-1); for(int i=0;i<sz;i++) for(int j=0;j<SIGMA_SIZE;j++) if(!val[ch[i][j]])res.mat[i][ch[i][j]]++; return res; }}ac;int main(){ while(scanf("%d%d",&N,&L)!=EOF) { ac.clear(); for(int i=1;i<=N;i++) { scanf("%s",s); ac.insert(s); } ac.getfail(); A=ac.getMatrix(); A=pow_sum(L); LL res=0; for(int i=0;i<A.n;i++)res+=A.mat[0][i]; A=Matrix(2); A.mat[0][0]=26; A.mat[1][0]=A.mat[1][1]=1; A=pow_mul(A,L); LL ans=0; ans+=A.mat[0][0]+A.mat[1][0]; ans--; cout<<ans-res<<endl; } return 0;}b方法:
#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<algorithm>using namespace std;typedef unsigned long long LL;const int maxn=50;const int SIGMA_SIZE=26;int N,L;char s[20];struct Matrix{ LL mat[61][61]; int n; Matrix(int x) { memset(mat,0,sizeof(mat)); n=x; } Matrix(){} Matrix operator*(Matrix a) { Matrix res(n); for(int k=0;k<n;k++) { for(int i=0;i<n;i++) { if(mat[i][k]==0)continue; for(int j=0;j<n;j++) res.mat[i][j]=(res.mat[i][j]+mat[i][k]*a.mat[k][j]); } } return res; } Matrix operator+(Matrix A) { Matrix res(A.n); for(int i=0;i<n;i++) for(int j=0;j<n;j++) res.mat[i][j]=(mat[i][j]+A.mat[i][j]); return res; }};Matrix A;Matrix pow_mul(Matrix A,LL x){ Matrix res(A.n); for(int i=0;i<=res.n;i++)res.mat[i][i]=1; while(x) { if(x&1)res=res*A; A=A*A; x>>=1; } return res;}struct AC{ int ch[maxn][26],val[maxn]; int fail[maxn],last[maxn]; int sz; void clear(){memset(ch[0],0,sizeof(ch[0]));sz=1;} int idx(char x){return x-'a';} void insert(char *s) { int n=strlen(s); int u=0; for(int i=0;i<n;i++) { int c=idx(s[i]); if(!ch[u][c]) { memset(ch[sz],0,sizeof(ch[sz])); val[sz]=0; ch[u][c]=sz++; } u=ch[u][c]; } val[u]=1; } void getfail() { queue<int> q; fail[0]=0; int u=0; for(int i=0;i<SIGMA_SIZE;i++) { u=ch[0][i]; if(u){fail[u]=last[u]=0;q.push(u);} } while(!q.empty()) { int r=q.front();q.pop(); if(val[fail[r]])val[r]=1; for(int c=0;c<SIGMA_SIZE;c++) { u=ch[r][c]; if(!u){ch[r][c]=ch[fail[r]][c];continue;} q.push(u); int v=fail[r]; while(v&&!ch[v][c])v=fail[v]; fail[u]=ch[v][c]; last[u]=val[fail[u]]?fail[u]:last[fail[u]]; } } } Matrix getMatrix() { Matrix res(sz+1); for(int i=0;i<sz;i++) for(int j=0;j<SIGMA_SIZE;j++) if(!val[ch[i][j]])res.mat[i][ch[i][j]]++; return res; }}ac;Matrix MatrixMul(Matrix A){ Matrix res(A.n*2); for(int i=0;i<A.n;i++) for(int j=0;j<A.n;j++)res.mat[i][j]=A.mat[i][j]; for(int i=0;i<A.n;i++)res.mat[i][i+A.n]=res.mat[i+A.n][i+A.n]=1; return res;}int main(){ while(scanf("%d%d",&N,&L)!=EOF) { ac.clear(); for(int i=1;i<=N;i++) { scanf("%s",s); ac.insert(s); } ac.getfail(); A=MatrixMul(ac.getMatrix()); A=pow_mul(A,L); LL res=0; for(int i=0;i<A.n;i++)res+=A.mat[0][i]; A=Matrix(2); A.mat[0][0]=26; A.mat[1][0]=A.mat[1][1]=1; A=pow_mul(A,L); LL ans=0; ans+=A.mat[0][0]+A.mat[1][0]; cout<<ans-res<<endl; } return 0;}
c方法:
#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<algorithm>using namespace std;typedef unsigned long long LL;const int maxn=50;const int SIGMA_SIZE=26;int N,L;char s[20];struct Matrix{ LL mat[30][30]; int n; Matrix(int x) { memset(mat,0,sizeof(mat)); n=x; } Matrix(){} Matrix operator*(Matrix a) { Matrix res(n); for(int k=0;k<n;k++) { for(int i=0;i<n;i++) { if(mat[i][k]==0)continue; for(int j=0;j<n;j++) res.mat[i][j]=(res.mat[i][j]+mat[i][k]*a.mat[k][j]); } } return res; } Matrix operator+(Matrix A) { Matrix res(A.n); for(int i=0;i<n;i++) for(int j=0;j<n;j++) res.mat[i][j]=(mat[i][j]+A.mat[i][j]); return res; }};Matrix A;Matrix pow_mul(Matrix A,LL x){ Matrix res(A.n); for(int i=0;i<=res.n;i++)res.mat[i][i]=1; while(x) { if(x&1)res=res*A; A=A*A; x>>=1; } return res;}struct AC{ int ch[maxn][26],val[maxn]; int fail[maxn],last[maxn]; int sz; void clear(){memset(ch[0],0,sizeof(ch[0]));sz=1;} int idx(char x){return x-'a';} void insert(char *s) { int n=strlen(s); int u=0; for(int i=0;i<n;i++) { int c=idx(s[i]); if(!ch[u][c]) { memset(ch[sz],0,sizeof(ch[sz])); val[sz]=0; ch[u][c]=sz++; } u=ch[u][c]; } val[u]=1; } void getfail() { queue<int> q; fail[0]=0; int u=0; for(int i=0;i<SIGMA_SIZE;i++) { u=ch[0][i]; if(u){fail[u]=last[u]=0;q.push(u);} } while(!q.empty()) { int r=q.front();q.pop(); if(val[fail[r]])val[r]=1; for(int c=0;c<SIGMA_SIZE;c++) { u=ch[r][c]; if(!u){ch[r][c]=ch[fail[r]][c];continue;} q.push(u); int v=fail[r]; while(v&&!ch[v][c])v=fail[v]; fail[u]=ch[v][c]; last[u]=val[fail[u]]?fail[u]:last[fail[u]]; } } } Matrix getMatrix() { Matrix res(sz+1); for(int i=0;i<sz;i++) for(int j=0;j<SIGMA_SIZE;j++) if(!val[ch[i][j]])res.mat[i][ch[i][j]]++; for(int i=0;i<=sz;i++)res.mat[i][sz]=1; return res; }}ac;int main(){ while(scanf("%d%d",&N,&L)!=EOF) { ac.clear(); for(int i=1;i<=N;i++) { scanf("%s",s); ac.insert(s); } ac.getfail(); A=ac.getMatrix(); A=pow_mul(A,L); LL res=0; for(int i=0;i<A.n;i++)res+=A.mat[0][i]; A=Matrix(2); A.mat[0][0]=26; A.mat[1][0]=A.mat[1][1]=1; A=pow_mul(A,L); LL ans=0; ans+=A.mat[0][0]+A.mat[1][0]; cout<<ans-res<<endl; } return 0;}
0 0
- AC自动机+矩阵(构造字符串 好)hdu2243
- HDU2243-AC自动机+矩阵
- AC自动机构造字符串(好)poj2778
- HDU2243-----AC自动机+矩阵乘法+矩阵公式
- hdu2243之AC自动机+矩阵乘法
- hdu2243 ac自动机+矩阵连乘
- hdu2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)
- HDU2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂+等比矩阵求和)
- 【hdu2243】【AC自动机】【矩阵乘法】考研路茫茫——单词情结
- HDU2243 考研路茫茫——单词情结 AC自动机DP矩阵优化
- hdu2243 考研路茫茫——单词情结 AC自动机+矩阵快速幂
- hdu2243---考研路茫茫——单词情结(AC自动机+矩阵+二分)
- HDU2243 考研路茫茫——单词情结 AC自动机+矩阵连乘
- [HDU2243]考研路茫茫-单词情节[Trie图|AC自动机|矩阵递推]
- hdu2243 考研路茫茫——单词情结 (AC自动机+矩阵快速幂)
- hdu 3962 Microgene (ac自动机+矩阵优化(好题))
- NEFU 1267 挑战字符串 (AC自动机+贪心)好题
- HDU2243 考研路茫茫――单词情结 AC自动机
- eclipse配置ndk
- iOS 拨打电话 拨打完以后会回到原来的应用
- 黑马程序员_(高新技术二)
- ubuntu 14.04输入法问题
- 关于输出用%lf和%f的问题
- AC自动机+矩阵(构造字符串 好)hdu2243
- Android——4.2 - 3G移植之路之libusb (一)
- Linux C++ 时间与日期
- STM8输入捕获
- iOS打电话的两种方法
- gcc生成静态链接库、动态链接库以及动态链接库包含静态链接库--笔记
- Android TV常用动画的效果,View选中变大且有阴影(手机也能用)
- accumulate函数用法
- Flex中创建Accordion报错