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;}
#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;}
- hdu 2243 poj 2778 AC自动机 + 经典矩阵乘法
- POJ 2778 AC自动机+矩阵乘法
- Poj 2778 [AC自动机,矩阵乘法]
- poj 2778 AC自动机+矩阵乘法
- poj 2778 ac自动机+矩阵乘法
- Poj 2778 [AC自动机,矩阵乘法]
- PKU 2778 HDU 2243 AC自动机 + 矩阵乘法
- poj 2778 DNA Sequence //AC自动机+矩阵乘法
- POJ 2778-DNA Sequence(AC自动机+矩阵乘法)
- HDU 2243 AC自动机->DP->附矩阵乘法板子
- ac自动机、矩阵乘法
- ac自动机+矩阵 poj 2778
- POJ-2778-ac自动机+矩阵
- poj 2778(AC自动机+矩阵)
- poj -- 2778 DNA Sequence && hdu -- 2243 考研路茫茫——单词情结(AC自动机 + 矩阵)
- HDU 2243 考研路茫茫——单词情结 AC自动机 加 矩阵乘法
- HDU 2243-考研路茫茫——单词情结(AC自动机+矩阵乘法+求补)
- POJ 2778 DNA Sequence(AC自动机+矩阵)
- classpath和环境变量设置
- nsfocus笔试题
- 图片文件
- php 用fsocket模拟浏览器POST GET
- android之拨打电话时在电话号码前加17951
- hdu 2243 poj 2778 AC自动机 + 经典矩阵乘法
- 接口ScriptEngine
- lucene 笔记;
- 队列的知识
- 来自大爱的IBM:Java 语言中的 volatile 变量
- 简单融合双系统 苹果虚拟Win8实用技巧
- 实验室设备管理系统(C语言实现)
- 浏览器兼容问题
- ADS1.2的简单使用