hdu 2243 poj 2778 AC自动机 + 经典矩阵乘法

来源:互联网 发布:电脑怎么优化系统 编辑:程序博客网 时间:2024/06/03 19:30

两个题差不多,只不过hdu上的恶心一点,对2^64取模,其实就相当于不用取模,所有的数都用unsigned __int64 即可,注意,无符号类型6-9就不是-3了哦

经典矩阵乘法是指求A+A^2+A^3+A^4+....A^n

做法在这里http://blog.csdn.net/haha593572013/article/details/8001943

然后这两题主要要做的就是构造trie图,继而构造出初始矩阵,mat[i][j]表示i走到j有几种走法 ,这个矩阵自乘n次之后就表示i走到j走n步有几种走法


hdu  2243


#include<cstdio>#include<cstring>typedef unsigned __int64 ULL;const int MAX = 65;int n,k,m,tn;struct  Mat {    ULL mat[MAX][MAX];    friend Mat operator *(Mat a,Mat b);    friend Mat operator +(Mat a,Mat b);    friend Mat operator ^(Mat a,int k);}E,A;ULL a[MAX][MAX];Mat operator +(Mat a,Mat b){    Mat c;    memset(c.mat,0,sizeof(c.mat));    for(int i=0;i<n;i++)        for(int j=0;j<n;j++)            c.mat[i][j]=(a.mat[i][j]+b.mat[i][j]);    return c;}Mat operator *(Mat a,Mat b){    Mat ans;    memset(ans.mat,0,sizeof(ans.mat));    for(int i=0;i<n;i++)        for(int j=0;j<n;j++)            for(int k=0;k<n;k++)            {                ULL tmp=a.mat[i][k]*b.mat[k][j];                ans.mat[i][j]=ans.mat[i][j]+tmp;            }            return ans;}Mat operator ^(Mat a,int k){    for(int i=0;i<n;i++) for(int j=0;j<n;j++) E.mat[i][j]= (i==j);    Mat ans=E;    while(k){        if(k&1) ans=ans*a;        a=a*a,k>>=1;    }    return ans;}const int M = 100;const int CD = 26;int fail[M];int Q[M];int ch[M][CD];int ID[128];int sz;int flag[M];void Init() {    fail[0]=0;    memset(ch[0],0,sizeof(ch[0]));    sz=1;    for(int i=0;i<26;i++) ID[i+'a']=i;}void Insert(char *s){    int p=0;    for(;*s;s++)    {        int c=ID[*s];        if(!ch[p][c])        {            memset(ch[sz],0,sizeof(ch[sz]));            flag[sz]=0;            ch[p][c]=sz++;        }        p=ch[p][c];    }    flag[p]=1;}void Construct(){    int *s=Q,*e=Q,v;    for(int i=0;i<CD;i++)    {        if(ch[0][i])        {            fail[ch[0][i]]=0;            *e++ = ch[0][i];        }    }    while(s!=e)    {        int u = *s++;        for(int i=0;i<CD;i++)        {            if(v=ch[u][i])            {                *e++=v;                fail[v]=ch[fail[u]][i];                flag[v]|=flag[fail[v]];            }            else             {                ch[u][i]=ch[fail[u]][i];            }        }    }}void init(){    memset(A.mat,0,sizeof(A.mat));    for(int i=0;i<tn;i++)    {        for(int j=0;j<tn;j++)        {            A.mat[i][j]=a[i][j];            A.mat[i][j+tn]=a[i][j];        }    }    for(int i=tn;i<n;i++)    {        for(int j=tn;j<n;j++)        {            if(i==j)A.mat[i][j]=1;        }    }}int main(){        int N;    int L;    char s[10];    while(scanf("%d%d",&N,&L)!=EOF)    {        memset(a,0,sizeof(a));        tn=1;  a[0][0]=26;   n=2*tn; init();        Mat ans=A^L;        ULL sum=ans.mat[0][1];        Init();        for(int i=0;i<N;i++)        {            scanf("%s",s);            Insert(s);        }        Construct();        Mat dp;        memset(dp.mat,0,sizeof(dp.mat));        for(int i=0;i<sz;i++)if(!flag[i])        {            for(int j=0;j<CD;j++) if(!flag[ch[i][j]])            {                dp.mat[i][ch[i][j]]++;            }        }        memset(a,0,sizeof(a));        for(int i=0;i<sz;i++)        {            for(int j=0;j<sz;j++)            {                a[i][j]=dp.mat[i][j];            }        }        tn=sz; n=2*tn;   init();        ans=A^L;        ULL sum2=0;        for(int j=tn;j<n;j++)        {            sum2+=ans.mat[0][j];        }        printf("%I64u\n",(sum-sum2));    }    return 0;}



poj  2778

#include <cstdio>#include <cstdlib>#include <string>#include <climits>#include <iostream>   #include <vector>#include <set>#include <cmath>#include <cctype>#include <algorithm>#include <sstream>#include <map>#include <cstring>#include <queue>using namespace std;const int mod = 100000;const int M = 100;const int CD = 4;int fail[M];int Q[M];int ch[M][CD];int ID[128];int val[M];int sz;void Init(){fail[0]=0;memset(ch[0],0,sizeof(ch[0]));sz=1;ID['A']=0;ID['T']=1;ID['G']=2;ID['C']=3;}void Insert(char *s){int p=0;for(;*s;s++){int c=ID[*s];if(!ch[p][c]){memset(ch[sz],0,sizeof(ch[sz]));val[sz]=0;ch[p][c]=sz++;}p=ch[p][c];}val[p]=1;}void Construct(){int  *s=Q,*e=Q;for(int i=0;i<CD;i++){if(ch[0][i]){fail[ch[0][i]] = 0;*e++ = ch[0][i];}}while(s!=e){int u = *s++;for(int i=0;i<CD;i++){int &v = ch[u][i];if(v){*e++ = v;fail[v]=ch[fail[u]][i];val[v]|=val[fail[v]];} else  {v=ch[fail[u]][i];}}}}long long dp[100][100];const int MAX = 100;int n;struct  Mat {int mat[MAX][MAX];Mat(){memset(mat,0,sizeof(mat));}void init(){for(int i=0;i<n;i++)for(int j=0;j<n;j++)              mat[i][j]= i==j;}void print(){printf("****************\n");for(int i=0;i<n;i++) for(int j=0;j<n;j++)   printf(j==n-1?"%d\n":"%d ",mat[i][j]);printf("fuckfuckfuckfuckfuck\n");}friend Mat operator *(Mat a,Mat b);friend Mat operator +(Mat a,Mat b);friend Mat operator ^(Mat a,int k);}E;Mat operator +(Mat a,Mat b){Mat c;for(int i=0;i<n;i++)for(int j=0;j<n;j++){c.mat[i][j]=a.mat[i][j]+b.mat[i][j];if(c.mat[i][j]>=mod) c.mat[i][j]-=mod;}return c;}Mat operator *(Mat a,Mat b){Mat ans;for(int i=0;i<n;i++)for(int j=0;j<n;j++){long long tmp=0;for(int k=0;k<n;k++){tmp+=(long long)a.mat[i][k]*b.mat[k][j];}ans.mat[i][j]=tmp%mod;} return ans;}Mat operator ^(Mat a,int k){Mat ans=E;while(k){if(k&1) ans=ans*a;a=a*a,k>>=1;}return ans;}int main() {char s[15];int k,m;while(scanf("%d%d",&m,&k)!=EOF){Init();for(int i=0;i<m;i++)  {scanf("%s",s);Insert(s);}Construct();n=sz;Mat ans;for(int i=0;i<sz;i++)if(!val[i]){for(int j=0;j<4;j++) if(!val[ch[i][j]]){                 ans.mat[i][ch[i][j]]++;}}//ans.print();E.init();ans=ans^k;//ans.print();int ret=0;for(int i=0;i<n;i++){ret+=ans.mat[0][i];if(ret>=mod) ret-=mod;}printf("%d\n",ret);}return 0;}