您的位置:首页 > 其它

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

2016-10-06 12:34 489 查看
题意:

和poj2778很像,这个是求包含病毒串的有多少个。那么我们求出不包含的在用总数相减就可以得到答案。

///对于2^64取mod 可以直接用unsigned long long

ACcode:

#include <bits/stdc++.h>
#define maxn 160
#define ll unsigned long long
using namespace std;
int m;
ll N;
char str[33];
struct Aho{
struct state{
int next[26];
int fail,cnt;
}s[maxn];
int size;
queue<int>q;
void init(){
size=1;
for(int i=0;i<maxn;++i){
memset(s[i].next,-1,sizeof(s[i].next));
s[i].fail=s[i].cnt=0;
}
while(q.size())q.pop();
}
void insert(char *str){
int n=strlen(str);
int now=0;
for(int i=0;i<n;++i){
int id=str[i]-'a';
if(s[now].next[id]==-1)
s[now].next[id]=size++;
now=s[now].next[id];
}
s[now].cnt=1;
}
struct Matrix{
ll mat[maxn][maxn];
};
Matrix mul(Matrix a,Matrix b){
Matrix ret;
memset(ret.mat,0,sizeof(ret.mat));
for(int i=0;i<size;++i)
for(int j=0;j<size;++j)
for(int k=0;k<size;++k)
ret.mat[i][j]+=a.mat[i][k]*b.mat[k][j];
return ret;
}
Matrix pow(Matrix a,ll k){
Matrix ret;
memset(ret.mat,0,sizeof(ret.mat));
for(int i=0;i<size;++i)ret.mat[i][i]=1;
while(k){
if(k&1)ret=mul(ret,a);
a=mul(a,a);
k>>=1;
}
return ret;
}
void build(){
s[0].fail=0;
for(int i=0;i<26;++i)
if(s[0].next[i]==-1)
s[0].next[i]=0;
else {
s[s[0].next[i]].fail=0;
q.push(s[0].next[i]);
}
while(q.size()){
int u=q.front();q.pop();
if(s[s[u].fail].cnt)s[u].cnt=1;
for(int i=0;i<26;++i){
if(s[u].next[i]==-1)
s[u].next[i]=s[s[u].fail].next[i];
else {
s[s[u].next[i]].fail=s[s[u].fail].next[i];
q.push(s[u].next[i]);
}
}
}
Matrix tmp;
memset(tmp.mat,0,sizeof(tmp.mat));
for(int i=0;i<size;++i){
if(s[i].cnt)continue;
for(int j=0;j<26;++j)
if(!s[s[i].next[j]].cnt)
tmp.mat[i][s[i].next[j]]++;
}
for(int i=0;i<=size;++i)
tmp.mat[i][size]=1;
size++;
tmp=pow(tmp,N);
ll ans=0;
for(int i=0;i<size;++i)
ans=(ans+tmp.mat[0][i]);
Matrix temp;
memset(temp.mat,0,sizeof(temp.mat));
temp.mat[0][0]=26;
temp.mat[1][0]=temp.mat[1][1]=1;
temp=pow(temp,N);
ll res=0;
for(int i=0;i<size;++i)res=(res+temp.mat[i][0]);
cout<<res-ans<<'\12';
}
}aho;
int main(){
while(cin>>m>>N){
aho.init();
for(int i=0;i<m;++i){
scanf("%s",str);
aho.insert(str);
}
aho.build();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: