hdu 2243 考研路茫茫——单词情结 ac自动机+矩阵快速幂

Posted hxer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 2243 考研路茫茫——单词情结 ac自动机+矩阵快速幂相关的知识,希望对你有一定的参考价值。

链接:http://acm.hdu.edu.cn/showproblem.php?pid=2243

题意:给定N(1<= N < 6)个长度不超过5的词根,问长度不超过L(L <231)的单词中至少含有一个词根的单词个数;结果mod 264.

基础:poj 2778DNA 序列求的是给定长度不含模式串的合法串的个数;串长度相当,都到了int上界了;

1.mod 264直接使用unsigned long long自然溢出即可;说的有些含蓄。。并且也容易想到是直接使用内置类型,要不然高精度的mod 2^64要跪;

2.本题是poj 2778的升级版,里面求的是范围内,并不是特定的长度,并且还是含有至少一个;那么直接从反面求解,即用总个数-不含有词根的个数;

3.对矩阵的操作,实现对连续离散指数求和; 对矩阵增加一列,全部为1,增加的行除了右下角为1外,其他均为0;

$\begin{pmatrix}
A\Rightarrow \begin{pmatrix}
A  & 1\\
0 & 1
\end{pmatrix}
\end{pmatrix}$

$ans = \sum \limits_{i=0}^{\rm size}mat\left [ 0 \right ]\left [ i \right ]$

同理求解:$\sum \limits_{i=0}^{\rm size}26^i$只需建立二维矩阵

\begin{vmatrix}
26 & 1\\
0 & 1
\end{vmatrix}之后直接矩阵快速幂即可;

 

// 15ms 1632k
#include<iostream> #include<cstdio> #include<cstring> #include<string.h> #include<algorithm> #include<vector> #include<cmath> #include<stdlib.h> #include<time.h> #include<stack> #include<set> #include<map> #include<queue> using namespace std; #define rep0(i,l,r) for(int i = (l);i < (r);i++) #define rep1(i,l,r) for(int i = (l);i <= (r);i++) #define rep_0(i,r,l) for(int i = (r);i > (l);i--) #define rep_1(i,r,l) for(int i = (r);i >= (l);i--) #define MS0(a) memset(a,0,sizeof(a)) #define MS1(a) memset(a,-1,sizeof(a)) #define MSi(a) memset(a,0x3f,sizeof(a)) #define inf 0x3f3f3f3f #define lson l, m, rt << 1 #define rson m+1, r, rt << 1|1 #define sqr(a) (a)*(a) typedef pair<int,int> PII; #define A first #define B second #define MK make_pair typedef __int64 ll; typedef unsigned long long ull; template<typename T> void read1(T &m) { T x=0,f=1;char ch=getchar(); while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();} while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();} m = x*f; } template<typename T> void read2(T &a,T &b){read1(a);read1(b);} template<typename T> void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);} template<typename T> void out(T a) { if(a>9) out(a/10); putchar(a%10+0); } int T,kase = 0,i,j,k,n,m,top; #define mod 100000 struct Matrix{ ull d[37][37]; int sz;//不能也弄成ull,否则int => ull会出错 Matrix(int r){MS0(d); sz = r;} void init(){ for(int i = 0;i < sz;i++) d[i][i] = 1; } Matrix operator*(const Matrix& a)const{ Matrix ans(a.sz); for(int i = 0;i < sz;i++) for(int j = 0;j < sz;j++){ for(int k = 0;k < sz;k++) ans.d[i][j] += d[i][k]*a.d[k][j]; } return ans; } void debug(){ rep0(i,0,sz){ rep0(j,0,sz) cout<<d[i][j]<<" "; cout<<endl; } } }; Matrix Pow(Matrix a,ll m) { Matrix ans(a.sz); ans.init(); while(m){ if(m&1) ans = ans*a; a = a*a; m >>= 1; } return ans; } const int sigma_size = 26; const int maxn = 37; struct Aho_Corasick{ int ch[maxn][sigma_size]; int val[maxn],f[maxn],last[maxn],cnt[maxn]; int sz; map<string,int> ms; Aho_Corasick(){} void init(){sz = 1;val[0] = 0; MS0(ch[0]);MS0(cnt);ms.clear();} int idx(char c){return c-a;} void Insert(char *s,int v){ int u = 0,n = strlen(s); for(int i = 0;i < n;i++){ int c = idx(s[i]); if(!ch[u][c]){ MS0(ch[sz]); val[sz] = 0; ch[u][c] = sz++; } u = ch[u][c]; } val[u] = v; } void getFail(){ queue<int> q; f[0] = 0; for(int c = 0;c < sigma_size;c++){ //初始化队列 int u = ch[0][c]; if(u) { f[u] = 0; q.push(u); last[u] = 0;} } while(!q.empty()){ int r = q.front();q.pop(); for(int c = 0;c < sigma_size;c++){ int u = ch[r][c]; if(!u) {ch[r][c] = ch[f[r]][c]; continue;}//实现压缩 q.push(u); int v = f[r]; while(v && !ch[v][c]) v = f[v]; f[u] = ch[v][c]; last[u] = val[f[u]]?f[u]:last[f[u]]; } } } Matrix Find(){ Matrix ans(sz+1); for(int i = 0;i < sz;i++){ if(val[i] || last[i]) continue; for(int j = 0;j < sigma_size;j++){ int v = ch[i][j]; if(val[v] || last[v]) continue; ans.d[i][v]++; } ans.d[i][sz] = 1;//添加一列保存前面的sigma和; } ans.d[sz][sz] = 1;//右下角 return ans; } }ac; char p[15]; int main() { ull n,L; //freopen("data.txt","r",stdin); while(scanf("%I64d%I64d",&n,&L) == 2) { ac.init(); rep1(i,1,n){ scanf("%s",p); ac.Insert(p,i); } ac.getFail(); Matrix ans = ac.Find(); ans = Pow(ans,L); ull cnt = 0; rep0(i,0,ans.sz) cnt += ans.d[0][i]; Matrix a(2);//求总和 a.d[0][0] = 26,a.d[0][1] = a.d[1][1] = 1; a = Pow(a,L); printf("%I64u\n",a.d[0][0]+a.d[0][1]-cnt); } return 0; }

 

以上是关于hdu 2243 考研路茫茫——单词情结 ac自动机+矩阵快速幂的主要内容,如果未能解决你的问题,请参考以下文章

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

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

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

HDU 2243 考研路茫茫――单词情结 ——(AC自动机+矩阵快速幂)

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

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