zoukankan      html  css  js  c++  java
  • HDU2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)

    POJ2778一样。这题是求长度不超过n且包含至少一个词根的单词总数。

    长度不超过n的单词总数记为Sn长度不超过n不包含词根的单词总数记为Tn

    答案就是,Sn-Tn

    Sn=26+262+263+...+26n

    Tn=A+A2+A3+...+An (A为AC自动机构造出来的矩阵)

    可以构造矩阵用快速幂求出Sn和Tn

    $$ egin{bmatrix} 26 & 1 \ 0 & 1 end{bmatrix} imes egin{bmatrix} S_n \ 26 end{bmatrix} = egin{bmatrix} S_{n+1} \ 26 end{bmatrix}$$

    $$ egin{bmatrix} A & E \ 0 & E end{bmatrix} imes egin{bmatrix} T_n \ A end{bmatrix} = egin{bmatrix} T_{n+1} \ A end{bmatrix}$$

    通过 $ egin{bmatrix} 26 & 1 \ 0 & 1 end{bmatrix} ^n imes egin{bmatrix} S_0 \ 26 end{bmatrix} = egin{bmatrix} S_n \ 26 end{bmatrix}$ 即可得到Sn,其中S0=0,Tn同理。

    另外题目结果mod 264这个直接把变量定义为unsigned __int64即可,溢出位数自动舍去。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<queue>
      4 using namespace std;
      5 int tn,ch[33][26],fail[33];
      6 bool flag[33];
      7 void insert(char *s){
      8     int x=0;
      9     for(int i=0; s[i]; ++i){
     10         int y=s[i]-'a';
     11         if(ch[x][y]==0) ch[x][y]=++tn;
     12         x=ch[x][y];
     13     }
     14     flag[x]=1;
     15 }
     16 void init(int x){
     17     memset(fail,0,sizeof(fail));
     18     queue<int> que;
     19     for(int i=0; i<26; ++i){
     20         if(ch[0][i]) que.push(ch[0][i]);
     21     }
     22     while(!que.empty()){
     23         int x=que.front(); que.pop();
     24         for(int i=0; i<26; ++i){
     25             if(ch[x][i]) que.push(ch[x][i]),fail[ch[x][i]]=ch[fail[x]][i];
     26             else ch[x][i]=ch[fail[x]][i];
     27             flag[ch[x][i]]|=flag[ch[fail[x]][i]];
     28         }
     29     }
     30 }
     31 void init(){
     32     memset(fail,0,sizeof(fail));
     33     queue<int> que;
     34     for(int i=0; i<26; ++i){
     35         if(ch[0][i]) que.push(ch[0][i]);
     36     }
     37     while(!que.empty()){
     38         int now=que.front(); que.pop();
     39         for(int i=0; i<26; ++i){
     40             if(ch[now][i]) que.push(ch[now][i]),fail[ch[now][i]]=ch[fail[now]][i];
     41             else ch[now][i]=ch[fail[now]][i];
     42             flag[ch[now][i]]|=flag[ch[fail[now]][i]];
     43         }
     44     }
     45 }
     46 struct Mat{
     47     unsigned long long m[66][66];
     48     int n;
     49 };
     50 Mat operator*(const Mat &m1,const Mat &m2){
     51     Mat m={0};
     52     m.n=m1.n;
     53     for(int i=0; i<m.n; ++i){
     54         for(int j=0; j<m.n; ++j){
     55             for(int k=0; k<m.n; ++k) m.m[i][j]+=m1.m[i][k]*m2.m[k][j];
     56         }
     57     }
     58     return m;
     59 }
     60 int main(){
     61     int n,l;
     62     char str[6];
     63     while(~scanf("%d%d",&n,&l)){
     64         tn=0;
     65         memset(ch,0,sizeof(ch));
     66         memset(flag,0,sizeof(flag));
     67         while(n--){
     68             scanf("%s",str);
     69             insert(str);
     70         }
     71         init();
     72         Mat se={0},sm={0};
     73         se.n=sm.n=2;
     74         for(int i=0; i<2; ++i) se.m[i][i]=1;
     75         sm.m[0][0]=26; sm.m[0][1]=1; sm.m[1][1]=1;
     76         n=l;
     77         while(n){
     78             if(n&1) se=se*sm;
     79             sm=sm*sm;
     80             n>>=1;
     81         }
     82         unsigned long long tot=se.m[0][1]*26;
     83 
     84         Mat te={0},tm={0};
     85         te.n=tm.n=tn+1<<1;
     86         for(int i=0; i<te.n; ++i) te.m[i][i]=1;
     87         for(int i=0; i<=tn; ++i){
     88             tm.m[i+tn+1][i+tn+1]=tm.m[i][i+tn+1]=1;
     89         }
     90         for(int i=0; i<=tn; ++i){
     91             if(flag[i]) continue;
     92             for(int j=0; j<26; ++j){
     93                 if(flag[ch[i][j]]) continue;
     94                 ++tm.m[i][ch[i][j]];
     95             }
     96         }    
     97         Mat tmp=tm; tmp.n=tn+1;
     98         n=l;
     99         while(n){
    100             if(n&1) te=te*tm;
    101             tm=tm*tm;
    102             n>>=1;
    103         }
    104         Mat tmp2; tmp2.n=tn+1;
    105         for(int i=0; i<=tn; ++i){
    106             for(int j=tn+1; j<te.n; ++j) tmp2.m[i][j-tn-1]=te.m[i][j];
    107         }
    108         tmp=tmp*tmp2;
    109         unsigned long long res=0;
    110         for(int i=0; i<=tn; ++i){
    111             res+=tmp.m[0][i];
    112         }
    113         printf("%llu
    ",tot-res);
    114     }
    115     return 0;
    116 }
  • 相关阅读:
    [Jenkins]admin用户登陆,提示登陆无效(之前登陆OK,三天没有登陆,突然提示登陆无效,重启无法解决)的解决方法
    科普技术贴:个人开发者的那些赚钱方式
    赚钱必看:独立开发者必知的一些总结
    【转】微信小程序给程序员带来的可能是一个赚钱的机遇
    20个编写现代 CSS 代码的建议
    Python爬虫入门一之综述
    Python学习基础知识概要
    文本框输入邮箱自动联想补全
    鼠标移到图片放大效果
    网站banner无缝轮播
  • 原文地址:https://www.cnblogs.com/WABoss/p/5168429.html
Copyright © 2011-2022 走看看