您的位置:首页 > 其它

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

2014-05-06 21:15 190 查看
题目链接

错的上头了...

这题是DNA的加强版,26^1 +26^2... - A^1-A^2...

先去学了矩阵的等比数列求和,学的是第二种方法,扩大矩阵的方法。剩下就是各种模板,各种套。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
#define LL unsigned __int64
#define N 100001
int t,trie
[26],que
,o
,fail
;
LL p[201][201],mat[201][201];
void CL()
{
memset(trie,-1,sizeof(trie));
memset(p,0,sizeof(p));
memset(o,0,sizeof(o));
t = 1;
}
void insert(char *s)
{
int i,root,len;
len = strlen(s);
root = 0;
for(i = 0; i < len; i ++)
{
if(trie[root][s[i]-'a'] == -1)
trie[root][s[i]-'a'] = t ++;
root = trie[root][s[i]-'a'];
}
o[root] = 1;
}
void build_ac()
{
int head,tail,front,i;
head = tail = 0;
for(i = 0; i < 26; i ++)
{
if(trie[0][i] != -1)
{
fail[trie[0][i]] = 0;
que[tail++] = trie[0][i];
}
else
{
trie[0][i] = 0;
}
}
while(head != tail)
{
front = que[head++];
if(o[fail[front]])
o[front] = 1;
for(i = 0; i < 26; i ++)
{
if(trie[front][i] != -1)
{
que[tail++] = trie[front][i];
fail[trie[front][i]] = trie[fail[front]][i];
}
else
{
trie[front][i] = trie[fail[front]][i];
}
}
}
}
void work()
{
int i,j;
for(i = 0; i < t; i ++)
{
if(o[i]) continue;
for(j = 0; j < 26; j ++)
{
if(o[trie[i][j]]) continue;
p[i][trie[i][j]] ++;
}
}
for(i = 0; i < t; i ++)
{
p[i][t+i] = p[t+i][t+i] = 1;
}
t <<= 1;
}
LL qmod(LL n)
{
int i,j,k;
LL c[201][201],ans = 0;
while(n)
{
if(n&1)
{
memset(c,0,sizeof(c));
for(i = 0; i < t; i ++)
{
for(j = 0; j < t; j ++)
{
for(k = 0; k < t; k ++)
{
c[i][j] += mat[i][k]*p[k][j];
}
}
}
memcpy(mat,c,sizeof(mat));
}
memset(c,0,sizeof(c));
for(i = 0; i < t; i ++)
{
for(j = 0; j < t; j ++)
{
for(k = 0; k < t; k ++)
{
c[i][j] += p[i][k]*p[k][j];
}
}
}
memcpy(p,c,sizeof(p));
n >>= 1;
}
for(i = t/2; i < t; i ++)
{
ans += mat[0][i];
}
return ans-1;
}

LL fastmod(LL a,LL k)
{
LL b = 1;
while(k)
{
if(k&1)
b = a*b;
a = a*a;
k = k/2;
}
return b;
}
LL getnum(LL p,LL k)
{
if (k <= 0) return 1;
if (k%2 == 0)
return ((getnum(p,k/2 - 1))*((1 + fastmod(p,k/2 + 1))) + fastmod(p,k/2));
else
return ((getnum(p,(k + 1)/2 - 1))*((1 + fastmod(p,(k + 1)/2))));
}
int main()
{
int i,j,m;
LL n;
char ch[101];
while(scanf("%d%I64u",&m,&n)!=EOF)
{
CL();
for(i = 1; i <= m; i ++)
{
scanf("%s",ch);
insert(ch);
}
build_ac();
work();
for(i = 0; i < t; i ++)
{
for(j = 0; j < t; j ++)
{
mat[i][j] = (i == j);
}
}
printf("%I64u\n",getnum(26,n)-1-qmod(n+1));
}
}


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