您的位置:首页 > 其它

HDU 2243 考研路茫茫——单词情结 AC自动机+DP+快速幂

2016-11-05 02:11 525 查看
与此题类似
http://blog.csdn.net/viphong/article/details/53039419
dp递推一样

在它的基础上多了一步求前缀和

solution是加多一维累计即可

最后求一个26+26^2 + 26^3 + 26^4 ...的一个快速幂相减就算是答案

对2^64取模就是 ull即可

printf+ull 是%llu。。。。

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
const int maxlen=200;
const int maxn=6*6;
const int all_size=26;
int trie[maxn][all_size];
int fail[maxn];
int tag[maxn];

int sz;
queue<int >Q;

const int N = 40;
const long long mod=10000000;
struct Matrix
{
unsigned long long mat

;
} ;
Matrix unit_matrix ;
long long n ;

int k=40;
Matrix mul(Matrix a, Matrix b) //矩阵相乘
{
Matrix res;
for(int i = 0; i < k; i++)
for(int j = 0; j < k; j++)
{
res.mat[i][j] = 0;
for(int t = 0; t < k; t++)
{
res.mat[i][j] += a.mat[i][t] * b.mat[t][j];
// res.mat[i][j] %= mod;
}
}

return res;
}

Matrix pow_matrix(Matrix a, long long m) //矩阵快速幂
{
Matrix res = unit_matrix;
while(m != 0)
{
if(m & 1)
res = mul(res, a);
a = mul(a, a);
m >>= 1;
}
return res;
}
struct Aho
{
int root;
int newnode()//静态创建新节点
{
memset(trie[sz],-1,sizeof trie[sz]);
tag[sz]=0;
sz++;
return sz-1;
}
void init()//初始化
{
sz=0;
newnode();
}
void insert(char s[],int id) //插入字符串构建ac自动机,构建trie树
{
int len=strlen(s),p=0;;
for (int i=0; i<len; i++)
{
int id=s[i]-'a';
if (trie[p][id]==-1)
trie[p][id]=newnode();
p=trie[p][id];
}
tag[p]=id; //结束标记
}
void getfail() //构建自动机fail指针
{
while(!Q.empty()) Q.pop();
fail[root]=root; //root指向root
for (int i=0; i<all_size; i++)
{
if (trie[root][i]==-1)//第一个字符不存在,指向root
trie[root][i]=root;
else //第一个字符的fail指针指向root
{
fail[trie[root][i]]=root;
Q.push(trie[root][i]); //并放入队列,待bfs扩展
}
}
while(!Q.empty())
{
int u=Q.front(); //取扩展节点
Q.pop();
if(tag[fail[u]]) tag[u]=1; //***如果之前是tag,直接标记
for (int i=0; i<all_size; i++)//遍历所有子节点
{
if (trie[u][i]==-1)//如果不存在,则子节点直接指向fail[u]节点的对应子节点
trie[u][i]=trie[fail[u]][i];
else //如果存在,则该节点的fail指针指向fail[u]节点对应的子节点
{
fail[trie[u][i]]=trie[fail[u]][i];
Q.push(trie[u][i]); //继续扩展
}
}
}
}

} aho;
char s[maxlen];
char name[15][55];

Matrix get(long long n)
{

k=sz+1;
Matrix c;
memset( c.mat ,0,sizeof c.mat);
for (int i=0; i<sz; i++)
{
for (int j=0; j<26; j++)
{
if ( !tag[trie[i][j] ])
c.mat[i][trie[i][j]]++;
}
}
for (int i=0;i<=sz;i++)
c.mat[i][sz]=1;
Matrix ans = pow_matrix(c, n);
// ans=mul(ori,ans);
return ans;
}

int main()
{
/* unsigned long long s=-1;
printf("%lld\n",s);*/
k=36+1;
int i, j, t;
for(i = 0; i < k; i++)
for(j = 0; j < k; j++)
unit_matrix.mat[i][j] = 0;
for(i = 0; i < k; i++) unit_matrix.mat[i][i] = 1;
long long m;
while(cin>>n>>m)
{
aho.init();
for (int i=0; i<n; i++)
{
scanf("%s",name[i]);
aho.insert(name[i],i+1);
}

aho.getfail();

Matrix ret= get(m);
unsigned long long ans=0;
for (int j=0;j<=sz;j++)
ans=(ans+ret.mat[0][j]);
ans--;
Matrix c,ori;
k=2;
// memset( c.mat ,0,sizeof c.mat);
// memset( ori.mat ,0,sizeof ori.mat);
c.mat[0][0]=26;
c.mat[0][1]=0;
c.mat[1][0]=26;
c.mat[1][1]=1;
ori.mat[0][0]=0;
ori.mat[0][1]=1;
ori.mat[1][0]=0;
ori.mat[1][1]=0;

c=pow_matrix(c,m);
ori=mul(ori,c);

unsigned long long out=ori.mat[0][0]-ans;
// cout<<out<<endl; //AC
printf("%llu\n",out ); //WA
}
return 0;
}



dp递推一样
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: