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

题意:长度不超过L,只由小写字母组成的,至少包含一个词根的单词,一共可能有多少个。

解题关键:利用补集转化的思想,先求一个词根也不包含的单词个数,然后用总的减去即可。长度不超过L需要用矩阵维数增加一倍来处理前缀和。

这里还有第二种考虑思路,只增加一维,自己写一个三维矩阵验证一下即可,最后一列每一行代表每一行的前缀和。

方法1:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<cstdlib>
  5 #include<cstring>
  6 #include<iostream>
  7 #include<queue>
  8 using namespace std;
  9 typedef unsigned long long ll;
 10 const int N=26;
 11 const int MAXN=42;
 12 struct mat{
 13     ll m[101][101];
 14 };
 15 ll m,n;
 16 struct Trie{
 17     int Next[MAXN][N],Fail[MAXN],root,tot;
 18     bool End[MAXN];
 19     int newnode(){
 20         for(int i=0;i<N;i++) Next[tot][i]=-1;
 21         End[tot++]=false;
 22         return tot-1;
 23     }
 24     void init(){
 25         tot=0;
 26         root=newnode();
 27     }
 28     void insert(char buf[]){
 29         int len=strlen(buf),now=root,k;
 30         for(int i=0;i<len;i++){
 31             k=buf[i]-'a';
 32             if(Next[now][k]==-1)  Next[now][k]=newnode();
 33             now=Next[now][k];
 34         }
 35         End[now]=true;
 36     }
 37     void build(){
 38         queue<int>que;
 39         Fail[root]=root;
 40         for(int i=0;i<N;i++){ 
 41             if(Next[root][i]==-1) Next[root][i]=root;
 42             else{
 43                 Fail[Next[root][i]]=root;
 44                 que.push(Next[root][i]);
 45             }
 46         }
 47         while(!que.empty()){
 48             int now=que.front();
 49             que.pop();
 50             if(End[Fail[now]]) End[now]=true;
 51             for(int i=0;i<N;i++){
 52                 if(Next[now][i]==-1) Next[now][i]=Next[Fail[now]][i];
 53                 else{
 54                     Fail[Next[now][i]]=Next[Fail[now]][i];
 55                     que.push(Next[now][i]);
 56                 }
 57             }
 58         }
 59     }
 60     mat get_mat(){
 61         mat B={0};
 62         for(int i=0;i<tot;i++){
 63             if(End[i]) continue;
 64             for(int j=0;j<N;j++){
 65                 if(End[Next[i][j]]==false) B.m[i][Next[i][j]]++;//不能直接置1 
 66             }
 67         }
 68         for(int i=0;i<tot;i++){
 69             B.m[i+tot][i]=B.m[i+tot][i+tot]=1;
 70         }
 71         return B;
 72     }
 73 };
 74 
 75 mat mul(mat &A,mat &B,int len){
 76     mat C={0};
 77     for(int i=0;i<len;i++){
 78         for(int j=0;j<len;j++){
 79             for(int k=0;k<len;k++){
 80                 C.m[i][j]+=A.m[i][k]*B.m[k][j];
 81             }
 82         }
 83     }
 84     return C;
 85 }
 86 
 87 mat pow(mat A,ll n,int len){
 88     mat B={0};
 89     for(int i=0;i<len;i++) B.m[i][i]=1;
 90     while(n){
 91         if(n&1) B=mul(B,A,len);
 92         A=mul(A,A,len);
 93         n>>=1;
 94     }
 95     return B;
 96 }
 97 
 98 Trie ac;
 99 char buf[10];
100 int main(){
101     while(scanf("%llu%llu",&m,&n)!=EOF){
102         ac.init();
103         for(int i=0;i<m;i++){
104             scanf("%s",buf);
105             ac.insert(buf);
106         }
107         ac.build();
108         mat B=ac.get_mat();
109         B=pow(B,n+1,2*ac.tot);
110         mat C={0},D={0},E={0};
111         for(int i=0;i<ac.tot;i++)    C.m[i][i]=1;
112         D=mul(B,C,2*ac.tot);
113         E.m[0][0]=26,E.m[0][1]=0,E.m[1][0]=E.m[1][1]=1;
114         E=pow(E,n+1,2);
115         ll res1=0,res2=E.m[1][0];
116         for(int i=0;i<ac.tot;i++){
117             if(i==0) D.m[ac.tot][i]-=1;
118             res1+=D.m[ac.tot][i];
119         }
120         printf("%llu\n",res2-1-res1);
121     }
122     return 0;
123 }

 法2:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<cstdlib>
  5 #include<cstring>
  6 #include<iostream>
  7 #include<queue>
  8 using namespace std;
  9 typedef unsigned long long ll;
 10 const int N=26;
 11 const int MAXN=42;
 12 struct mat{
 13     ll m[101][101];
 14 };
 15 ll m,n;
 16 struct Trie{
 17     int Next[MAXN][N],Fail[MAXN],root,tot;
 18     bool End[MAXN];
 19     int newnode(){
 20         for(int i=0;i<N;i++) Next[tot][i]=-1;
 21         End[tot++]=false;
 22         return tot-1;
 23     }
 24     void init(){
 25         tot=0;
 26         root=newnode();
 27     }
 28     void insert(char buf[]){
 29         int len=strlen(buf),now=root,k;
 30         for(int i=0;i<len;i++){
 31             k=buf[i]-'a';
 32             if(Next[now][k]==-1)  Next[now][k]=newnode();
 33             now=Next[now][k];
 34         }
 35         End[now]=true;
 36     }
 37     void build(){
 38         queue<int>que;
 39         Fail[root]=root;
 40         for(int i=0;i<N;i++){ 
 41             if(Next[root][i]==-1) Next[root][i]=root;
 42             else{
 43                 Fail[Next[root][i]]=root;
 44                 que.push(Next[root][i]);
 45             }
 46         }
 47         while(!que.empty()){
 48             int now=que.front();
 49             que.pop();
 50             if(End[Fail[now]]) End[now]=true;
 51             for(int i=0;i<N;i++){
 52                 if(Next[now][i]==-1) Next[now][i]=Next[Fail[now]][i];
 53                 else{
 54                     Fail[Next[now][i]]=Next[Fail[now]][i];
 55                     que.push(Next[now][i]);
 56                 }
 57             }
 58         }
 59     }
 60     mat get_mat(){
 61         mat B={0};
 62         for(int i=0;i<=tot;i++) B.m[i][tot]=1;
 63         for(int i=0;i<tot;i++){
 64             if(End[i]) continue;
 65             for(int j=0;j<N;j++){
 66                 if(End[Next[i][j]]==false) B.m[i][Next[i][j]]++;//不能直接置1 
 67             }
 68         }
 69         return B;
 70     }
 71 };
 72 
 73 mat mul(mat &A,mat &B,int len){
 74     mat C={0};
 75     for(int i=0;i<len+1;i++){
 76         for(int j=0;j<len+1;j++){
 77             for(int k=0;k<len+1;k++){
 78                 C.m[i][j]+=A.m[i][k]*B.m[k][j];
 79             }
 80         }
 81     }
 82     return C;
 83 }
 84 
 85 mat pow(mat A,ll n,int len){
 86     mat B={0};
 87     for(int i=0;i<len;i++) B.m[i][i]=1;
 88     while(n){
 89         if(n&1) B=mul(B,A,len);
 90         A=mul(A,A,len);
 91         n>>=1;
 92     }
 93     return B;
 94 }
 95 
 96 Trie ac;
 97 char buf[10];
 98 int main(){
 99     while(scanf("%llu%llu",&m,&n)!=EOF){
100         ac.init();
101         for(int i=0;i<m;i++){
102             scanf("%s",buf);
103             ac.insert(buf);
104         }
105         ac.build();
106         mat B=ac.get_mat();
107         
108         ll res1,res2;
109         B=pow(B,n+1,ac.tot);
110         res1=B.m[0][ac.tot]-1;
111         
112         mat E={0};
113         E.m[0][0]=26,E.m[0][1]=0,E.m[1][0]=E.m[1][1]=1;
114         E=pow(E,n+1,2);
115         res2=E.m[1][0];
116 
117         printf("%llu\n",res2-1-res1);
118     }
119     return 0;
120 }

 

posted @ 2017-09-13 03:16  Elpsywk  阅读(189)  评论(0编辑  收藏  举报