Hdu 2243 考研路茫茫——单词情结 (AC自己主动机+矩阵)
哎哟喂。中文题。
。
。不说题意了。
首先做过POJ 2778能够知道AC自己主动机是能够求出长度为L的串中不含病毒串的数量的。
POJ 2778的大概思路就是先用全部给的病毒串建一个AC自己主动机。然后将AC自己主动机上全部非单词节点连一个边。
离散数学中有说道。假设矩阵A 中的 [i][j] 表示 i节点通过一条边能够走到j节点的方法数。
那么A*A这个矩阵的[i][j]就表示 i 节点到j 节点通过两条边能够走到j节点的方法数。
既然知道这种方法。我们就明白要求什么。
ans= 26+26^2+26^3+....+26^L - 长度为1不含病毒串的数量-长度为2不含病毒串的数量-...-长度为L不含病毒串的数量。
解决两个问题
对 2^64取模。知道2^64是 long long 的最大值,那么我们直接开成unsigned long long ...然后放心大胆的运算,溢出便是取模。
我们知道矩阵 matrix ^ L 可是要求出全部的和。就要用矩阵里套矩阵。也就是求矩阵的和。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define N 35
using namespace std;
typedef unsigned long long ll;
const char tab = 'a';
const int max_next = 26;
struct trie
{
struct trie *fail;
struct trie *next[max_next];
int isword;
int index;
};
struct AC
{
trie *que[100005],*root,ac[100005];
int head,tail;
int idx;
trie *New()
{
trie *temp=&ac[idx];
for(int i=0;i<max_next;i++)temp->next[i]=NULL;
temp->fail=NULL;
temp->isword=0;
temp->index=idx++;
return temp;
}
void init()
{
idx=0;
root=New();
}
void Insert(trie *root,char *word,int len){
trie *t=root;
for(int i=0;i<len;i++){
if(t->next[word[i]-tab]==NULL)
t->next[word[i]-tab]=New();
t=t->next[word[i]-tab];
}
t->isword++;
}
void acbuild(trie *root){
int head=0,tail=0;
que[tail++]=root;
root->fail=NULL;
while(head<tail){
trie *temp=que[head++],*p;
for(int i=0;i<max_next;i++){
if(temp->next[i]){
if(temp==root)temp->next[i]->fail=root;
else {
p=temp->fail;
while(p!=NULL){
if(p->next[i]){
temp->next[i]->fail=p->next[i];
break;
}
p=p->fail;
}
if(p==NULL)temp->next[i]->fail=root;
}
if(temp->next[i]->fail->isword)temp->next[i]->isword++;
que[tail++]=temp->next[i];
}
else if(temp==root)temp->next[i]=root;
else temp->next[i]=temp->fail->next[i];
}
}
}
void tra()
{
for(int i=0;i<idx;i++)
{
if(ac[i].fail!=NULL)printf("fail = %d ",ac[i].fail->index);
for(int k=0;k<max_next;k++)
printf("%d ",ac[i].next[k]->index);
puts("");
}
}
}sa; struct matrix
{
int r,c;
ll data[N][N];
matrix(){}
matrix(int _r,int _c):r(_r),c(_c){memset(data,0,sizeof data);}
friend matrix operator * (const matrix A,const matrix B)
{
matrix res;
res.r=A.r;res.c=B.c;
memset(res.data,0,sizeof res.data);
for(int i=0;i<A.r;i++)
{
for(int j=0;j<B.c;j++)
{
for(int k=0;k<A.c;k++)
{
if(A.data[i][k] && B.data[k][j]){
res.data[i][j]+=A.data[i][k]*B.data[k][j];
//res.data[i][j]%=mod;
}
}
}
}
return res;
}
friend matrix operator + (const matrix A,const matrix B)
{
matrix res;
res.r=A.r;res.c=A.c;
memset(res.data,0,sizeof res.data);
for(int i=0;i<A.r;i++)
{
for(int j=0;j<A.c;j++)
{
res.data[i][j]=A.data[i][j]+B.data[i][j];
//res.data[i][j]%=mod;
}
}
return res;
}
friend matrix operator - (const matrix A,const matrix B)
{
matrix res;
res.r=A.r;res.c=A.c;
memset(res.data,0,sizeof res.data);
for(int i=0;i<A.r;i++)
{
for(int j=0;j<A.c;j++)
{
res.data[i][j]=A.data[i][j]-B.data[i][j];
//res.data[i][j]=(res.data[i][j]%mod+mod)%mod;
}
}
return res;
}
friend matrix operator ^ (matrix A,int n)
{
matrix res;
res.r=A.r;res.c=A.c;
memset(res.data,0,sizeof res.data);
for(int i=0;i<A.r;i++)res.data[i][i]=1; while(n)
{
if(n&1)res=res*A;
A=A*A;
n>>=1;
}
return res;
}
void print()
{
for(int i=0;i<r;i++)
{
for(int j=0;j<c;j++)
printf("%d ",data[i][j]);
puts("");
}
}
}E,zero; char word[10];
struct supermatrix
{
matrix ret[2][2];
friend supermatrix operator * (const supermatrix A,const supermatrix B)
{
supermatrix res;
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)res.ret[i][j]=zero; for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
for(int k=0;k<2;k++)
{
res.ret[i][j]=res.ret[i][j]+A.ret[i][k]*B.ret[k][j];
}
}
}
return res;
}
friend supermatrix operator + (const supermatrix A,const supermatrix B)
{
supermatrix res;
for(int i=0;i<2;i++)for(int j=0;j<2;j++)res.ret[i][j]=zero;
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
res.ret[i][j]=A.ret[i][j]+B.ret[i][j];
}
}
return res;
}
friend supermatrix operator ^ (supermatrix A,ll n)
{
supermatrix res;
for(int i=0;i<2;i++)for(int j=0;j<2;j++)res.ret[i][j]=zero;
for(int i=0;i<2;i++)res.ret[i][i]=E;
while(n)
{
if(n&1)res=res*A;
A=A*A;
n>>=1;
}
return res;
}
}; int main()
{
int n,L;
while(scanf("%d%d",&n,&L)!=EOF)
{
sa.init();
for(int i=1;i<=n;i++)
{
scanf("%s",word);
sa.Insert(sa.root,word,strlen(word));
}
sa.acbuild(sa.root); E=matrix(sa.idx,sa.idx);
for(int i=0;i<N;i++)E.data[i][i]=1;
zero=matrix(sa.idx,sa.idx); matrix origin=matrix(sa.idx,sa.idx); for(int i=0;i<sa.idx;i++)
{
if(sa.ac[i].isword==0)
{
for(int d=0;d<max_next;d++)
{
int temp=sa.ac[i].next[d]->index;
if(sa.ac[i].next[d]->isword==0)
{
origin.data[i][temp]++;
}
}
}
}
supermatrix A;
A.ret[0][0]=A.ret[0][1]=E;
A.ret[1][0]=zero;
A.ret[1][1]=origin; A=A^L;
supermatrix f;
f.ret[0][0]=f.ret[0][1]=f.ret[1][1]=zero;
f.ret[1][0]=origin;
matrix fans=A.ret[0][0]*zero+A.ret[0][1]*origin;
ll ans=0;
for(int i=0;i<sa.idx;i++)
{
if(sa.ac[i].isword==0)
{
ans+=fans.data[0][i];
}
} matrix I=matrix(2,2);
I.data[0][0]=I.data[0][1]=1;
I.data[1][1]=26;
I.data[1][0]=0;
I=I^L; printf("%I64u\n",I.data[0][1]*26-ans);
}
return 0;
}
Hdu 2243 考研路茫茫——单词情结 (AC自己主动机+矩阵)的更多相关文章
- hdu 2243 考研路茫茫——单词情结(AC自动+矩阵)
考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- hdu 2243 考研路茫茫——单词情结 ac自动机+矩阵快速幂
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2243 题意:给定N(1<= N < 6)个长度不超过5的词根,问长度不超过L(L <23 ...
- hdu 2243 考研路茫茫——单词情结 AC自动机 矩阵幂次求和
题目链接 题意 给定\(N\)个词根,每个长度不超过\(5\). 问长度不超过\(L(L\lt 2^{31})\),只由小写字母组成的,至少包含一个词根的单词,一共可能有多少个? 思路 状态(AC自动 ...
- HDU 2243 考研路茫茫——单词情结(AC自动机+DP+快速幂)
题目链接 错的上头了... 这题是DNA的加强版,26^1 +26^2... - A^1-A^2... 先去学了矩阵的等比数列求和,学的是第二种方法,扩大矩阵的方法.剩下就是各种模板,各种套. #in ...
- hdu 2243 考研绝望——复杂的文字(AC自己主动机+矩阵高速功率)
pid=2243" target="_blank" style="">题目链接:hdu 2243 考研路茫茫--单词情结 题目大意:略. 解题思 ...
- HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵)
考研路茫茫——单词情结 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- HDU 2243 考研路茫茫——单词情结
考研路茫茫——单词情结 Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID ...
- HDU 2243考研路茫茫——单词情结 (AC自动机+矩阵快速幂)
背单词,始终是复习英语的重要环节.在荒废了3年大学生涯后,Lele也终于要开始背单词了. 一天,Lele在某本单词书上看到了一个根据词根来背单词的方法.比如"ab",放在单词前一般 ...
- HDU 2243 考研路茫茫——单词情结(AC自动机+矩阵快速幂)
http://acm.hdu.edu.cn/showproblem.php?pid=2243 题意: 给出m个模式串,求长度不超过n的且至少包含一个模式串的字符串个数. 思路: 如果做过poj2778 ...
随机推荐
- python面试经典315
期待的是可以检验自己学习的成功:苦逼的是怎么又有东西没记住,但我们依然每天坚持一遍.一遍又一遍指导记住为止. 第一部分 Python基础篇(80题) 为什么学习Python? 通过什么途径学习的Pyt ...
- 【Cocos2D研究院之游戏开发】
http://www.xuanyusong.com/archives/category/ios/cocos2d_game 分类目录归档:[Cocos2D研究院之游戏开发] 201211-19 Co ...
- pymongo.errors.BulkWriteError错误排解
在mongodb进行数据库操作的时候触发异常 pymongo Error: pymongo.errors.BulkWriteError: batch op errors occurred 这种问题 ...
- 使用composer出现 Cannot find module (SNMPv2-TC) 等错误的解决方法
Cannot find module (SNMPv2-TC): At line 10 in /usr/share/snmp/mibs/UCD-DLMOD-MIB.txt Cannot find mod ...
- Laravel5.1忽略Csrf验证的方法
在/App/Http/middleware/VerifyCsrfToken.php 文件的protected $except里面加入路由地址
- 基于SpringMVC的上传文件实现
基于SpringMVC的上传文件实现 1.项目源码 源码地址:upload 2.关键代码 @RequestMapping("/upload2") public void datal ...
- Netty源码学习(零)前言
本系列文章将介绍Netty的工作机制,以及分析Netty的主要源码. 基于的版本是4.1.15.Final(2017.08.24发布) 水平有限,如有谬误请留言指正 参考资料 the_flash的简书 ...
- 51nod 1007 正整数分组【01背包变形】
1007 正整数分组 基准时间限制:1 秒 空间限制:131072 KB 分值: 10 难度:2级算法题 收藏 关注 将一堆正整数分为2组,要求2组的和相差最小. 例如:1 2 3 4 5,将1 ...
- 洛谷——P1147 连续自然数和
P1147 连续自然数和 题目描述 对一个给定的自然数M,求出所有的连续的自然数段,这些连续的自然数段中的全部数之和为M. 例子:1998+1999+2000+2001+2002 = 10000,所以 ...
- [BZOJ 3108] 图的逆变换
Link: BZOJ 3108 传送门 Solution: 样例教你做题系列 观察第三个输出为No的样例,发现只要存在$edge(i,k),edge(j,k)$,那么$i,j$的出边一定要全部相同 于 ...