HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)
2017-08-27 11:33
453 查看
http://acm.hdu.edu.cn/showproblem.php?pid=2243
题意:
给出m个模式串,求长度不超过n的且至少包含一个模式串的字符串个数。
思路:
如果做过poj2778的话,那么这题相对来说就会容易一些。
如果直接去计算的话,情况很复杂,和poj2778一样,我们先求出不包含模式串的个数,最后只需要相减就可以。
因为这道题目长度只要不超过n就可以,所以在构造矩阵的时候需要多加一列,该列值每行全设为1(这样最后一列的值就是对上一个矩阵每一行的和,完美计算了了各种长度的个数之和)。最后得到的值res-1就是不包含的情况个数(减去1是因为一开始的时候多算了1)。
接下来计算一下所有情况的个数,$f(n)=1+26^1+26^2+...+26^n$,可以得出$f(n)=26*f(n-1)+1$,于是这就能构造出一个矩阵了,最后得到的res-1就是所有的情况个数。
题意:
给出m个模式串,求长度不超过n的且至少包含一个模式串的字符串个数。
思路:
如果做过poj2778的话,那么这题相对来说就会容易一些。
如果直接去计算的话,情况很复杂,和poj2778一样,我们先求出不包含模式串的个数,最后只需要相减就可以。
因为这道题目长度只要不超过n就可以,所以在构造矩阵的时候需要多加一列,该列值每行全设为1(这样最后一列的值就是对上一个矩阵每一行的和,完美计算了了各种长度的个数之和)。最后得到的值res-1就是不包含的情况个数(减去1是因为一开始的时候多算了1)。
接下来计算一下所有情况的个数,$f(n)=1+26^1+26^2+...+26^n$,可以得出$f(n)=26*f(n-1)+1$,于是这就能构造出一个矩阵了,最后得到的res-1就是所有的情况个数。
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<vector> #include<stack> #include<queue> #include<cmath> #include<map> #include<set> using namespace std; typedef long long ll; const int INF = 0x3f3f3f3f; const int maxn=10000+5; int n, m, num; char s[20]; struct Trie { int son[30]; int cnt; int fail; }t[100]; struct Matrix { unsigned long long mat[40][40], n; Matrix(){} Matrix(int _n) { n=_n; for(int i=0;i<n;i++) for(int j=0;j<n;j++) mat[i][j]=0; } Matrix operator*(const Matrix& b) const { Matrix c=Matrix(n); for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { for(int k=0;k<n;k++) { c.mat[i][j]+=mat[i][k]*b.mat[k][j]; } } } return c; } }; void init(int x) { t[x].fail=0; t[x].cnt=0; memset(t[x].son,0,sizeof(t[x].son)); } void trie(char *s) { int n=strlen(s); int x=0; for(int i=0;i<n;i++) { int c=s[i]-'a'+1; if(!t[x].son[c]) { num++; init(num); t[x].son[c]=num; } x=t[x].son[c]; } t[x].cnt=1; } void buildAC() { queue<int> Q; for(int i=1;i<=26;i++) if(t[0].son[i]) Q.push(t[0].son[i]); while(!Q.empty()) { int x=Q.front(); Q.pop(); int fail=t[x].fail; for(int i=1;i<=26;i++) { int y=t[x].son[i]; if(y) { t[y].fail=t[fail].son[i]; t[y].cnt|=t[t[fail].son[i]].cnt; //这儿很重要,这个标记需要传递 Q.push(y); } else t[x].son[i]=t[fail].son[i]; } } } Matrix getMatrix() { Matrix c=Matrix(num+2); for(int i=0;i<=num;i++) { for(int j=1;j<=26;j++) { if(t[t[i].son[j]].cnt==0) c.mat[i][t[i].son[j]]++; } } for(int i=0; i<num+2; i++) c.mat[i][num+1]=1; return c; } Matrix q_pow(Matrix base, int n) { Matrix ans=Matrix(base.n); for(int i=0;i<ans.n;i++) ans.mat[i][i]=1; while(n) { if(n&1) ans=ans*base; base=base*base; n>>=1; } return ans; } int main() { //freopen("in.txt","r",stdin); while(~scanf("%d%d",&m,&n)) { init(0); num=0; for(int i=1;i<=m;i++) { scanf("%s",s); trie(s); } buildAC(); Matrix c=getMatrix(); c = q_pow(c,n); unsigned long long res = 0; for(int i=0;i<c.n;i++) res+=c.mat[0][i]; res--; c=Matrix(2); c.mat[0][0]=26; c.mat[0][1]=c.mat[1][1]=1; c=q_pow(c,n); unsigned long long ans=c.mat[0][0]+c.mat[0][1]; ans--; ans-=res; cout<<ans<<endl; } return 0; }
相关文章推荐
- hdu 2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)
- hdu_2243 _考研路茫茫――单词情结 (AC自动机+矩阵快速幂+...)
- HDU 2243 考研路茫茫——单词情结 (AC自动机+矩阵快速幂求和)
- HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)
- HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵)
- hdu 2243考研路茫茫——单词情结—解题报告
- 考研路茫茫--单词情结 - HDU 2243(AC自动机+矩阵乘法)
- HDU 2243 考研路茫茫——单词情结(自动机DP+矩阵)
- hdu 2243 考研路茫茫——单词情结(AC自动+矩阵)
- hdu 2243 考研路茫茫——单词情结 AC自动机+转移矩阵
- HDU 2243 考研路茫茫——单词情结 求长度小于等于L的通路总数的方法
- HDU 2243 考研路茫茫——单词情结(自动机)
- HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵幂)
- HDU 2243 考研路茫茫——单词情结(AC自动机+DP+快速幂)
- HDU 2243 考研路茫茫——单词情结
- HDU 2243-考研路茫茫——单词情结(AC自动机+矩阵乘法+求补)
- AC自动机专题——P - 考研路茫茫――单词情结 HDU - 2243 矩阵快速幂+AC自动机
- HDU 2243 考研路茫茫——单词情结
- HDU 2243 考研路茫茫——单词情结 AC自动机+DP+快速幂
- hdu_2243_考研路茫茫——单词情结(AC自动机+矩阵)