zoukankan      html  css  js  c++  java
  • [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
    ",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
    ",res2-1-res1);
    118     }
    119     return 0;
    120 }
  • 相关阅读:
    我的第一个作业
    团队任务3:第一次冲刺
    课后作业3:个人项目(词频统计及其效能分析)
    课后作业2:个人项目
    一切的开始,从未有过的改变——课后作业1:准备
    Fiddler 添加IP显示、响应时间功能
    Jmeter所有结果分析
    云盘资源爬取利器 fmv
    python 中的 sys , os 模块用法总结
    Python 编写登录接口
  • 原文地址:https://www.cnblogs.com/elpsycongroo/p/7513098.html
Copyright © 2011-2022 走看看