标签:set logs matrix while pid name pre scan pen
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就是所有的情况个数。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<stack> 7 #include<queue> 8 #include<cmath> 9 #include<map> 10 #include<set> 11 using namespace std; 12 typedef long long ll; 13 const int INF = 0x3f3f3f3f; 14 const int maxn=10000+5; 15 16 int n, m, num; 17 char s[20]; 18 19 struct Trie 20 { 21 int son[30]; 22 int cnt; 23 int fail; 24 }t[100]; 25 26 struct Matrix 27 { 28 unsigned long long mat[40][40], n; 29 Matrix(){} 30 Matrix(int _n) 31 { 32 n=_n; 33 for(int i=0;i<n;i++) 34 for(int j=0;j<n;j++) 35 mat[i][j]=0; 36 } 37 Matrix operator*(const Matrix& b) const 38 { 39 Matrix c=Matrix(n); 40 for(int i=0;i<n;i++) 41 { 42 for(int j=0;j<n;j++) 43 { 44 for(int k=0;k<n;k++) 45 { 46 c.mat[i][j]+=mat[i][k]*b.mat[k][j]; 47 } 48 } 49 } 50 return c; 51 } 52 }; 53 54 void init(int x) 55 { 56 t[x].fail=0; 57 t[x].cnt=0; 58 memset(t[x].son,0,sizeof(t[x].son)); 59 } 60 61 void trie(char *s) 62 { 63 int n=strlen(s); 64 int x=0; 65 for(int i=0;i<n;i++) 66 { 67 int c=s[i]-‘a‘+1; 68 if(!t[x].son[c]) 69 { 70 num++; 71 init(num); 72 t[x].son[c]=num; 73 } 74 x=t[x].son[c]; 75 } 76 t[x].cnt=1; 77 } 78 79 void buildAC() 80 { 81 queue<int> Q; 82 for(int i=1;i<=26;i++) if(t[0].son[i]) Q.push(t[0].son[i]); 83 while(!Q.empty()) 84 { 85 int x=Q.front(); Q.pop(); 86 int fail=t[x].fail; 87 for(int i=1;i<=26;i++) 88 { 89 90 int y=t[x].son[i]; 91 if(y) 92 { 93 t[y].fail=t[fail].son[i]; 94 t[y].cnt|=t[t[fail].son[i]].cnt; //这儿很重要,这个标记需要传递 95 Q.push(y); 96 } 97 else t[x].son[i]=t[fail].son[i]; 98 } 99 } 100 } 101 102 Matrix getMatrix() 103 { 104 Matrix c=Matrix(num+2); 105 for(int i=0;i<=num;i++) 106 { 107 for(int j=1;j<=26;j++) 108 { 109 if(t[t[i].son[j]].cnt==0) c.mat[i][t[i].son[j]]++; 110 } 111 } 112 for(int i=0; i<num+2; i++) c.mat[i][num+1]=1; 113 return c; 114 } 115 116 117 Matrix q_pow(Matrix base, int n) 118 { 119 Matrix ans=Matrix(base.n); 120 for(int i=0;i<ans.n;i++) ans.mat[i][i]=1; 121 while(n) 122 { 123 if(n&1) ans=ans*base; 124 base=base*base; 125 n>>=1; 126 } 127 return ans; 128 } 129 130 int main() 131 { 132 //freopen("in.txt","r",stdin); 133 while(~scanf("%d%d",&m,&n)) 134 { 135 init(0); 136 num=0; 137 for(int i=1;i<=m;i++) 138 { 139 scanf("%s",s); 140 trie(s); 141 } 142 buildAC(); 143 Matrix c=getMatrix(); 144 c = q_pow(c,n); 145 unsigned long long res = 0; 146 for(int i=0;i<c.n;i++) res+=c.mat[0][i]; 147 res--; 148 c=Matrix(2); 149 c.mat[0][0]=26; 150 c.mat[0][1]=c.mat[1][1]=1; 151 c=q_pow(c,n); 152 unsigned long long ans=c.mat[0][0]+c.mat[0][1]; 153 ans--; 154 ans-=res; 155 cout<<ans<<endl; 156 } 157 return 0; 158 }
HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)
标签:set logs matrix while pid name pre scan pen
原文地址:http://www.cnblogs.com/zyb993963526/p/7439949.html