关于PE458(project euler 458 Permutations of Project)的思考

本文探讨了Project Euler中第458题的解决思路,作者在实现算法过程中意识到原本错误估计了状态数量。指出长度为6的排列只有720种,即便加上其他情况,总状态数也不会超过1000,因此通过1000的三次方矩阵乘法来求解是可行的方法。
摘要由CSDN通过智能技术生成
本文回顾了PE458的解题过程中遇到的问题,介绍了trie,AC自动机,自动机化简算法.

题意:给定project 这7个字母(等价于互不相同的7个字母),问长度为10^12的由这7个字母组成的串且串中任意连续7个字母中不包含所有的7个字母(即:任意连续7个字母不是project的排列)有多少个,答案对1e9取模.

尝试用AC自动机和矩阵二分解决问题:

首先想到的构造一个自动机,能够判断一个串是否满足要求.假定构造出来,我们可以构造转移矩阵tran[i][j],当在状态机j状态下输入某个字母并转移到i状态,tran[i][j]的值增加1.给定列向量x[0] = (1, 0, 0, ...)', x[i] = tran * x[i-1], 第一个分量的状态表示空串的状态.于是x[i][j]就表示长度为i,且状态是j的串的个数.考虑其中需要的状态,相加即可.

怎么构造这个自动机呢,当然用AC自动机了.也就是说,先构造一个trie,然后把7!个不合法的串插入到这个trie中.在构造的trie中,还有一些状态在接受输入时没有下一个状态,所以下一步是把这些状态填满.

考虑一个非法状态,无论输入是什么,下一个状态还是本身,因为只要某处出现project的排列了,无论后面的输入何如,这个串都是非法的.

考虑其它中间状态,这个状态对应一个字符串s,|s|>0 .我们只需要找出一个串t,|t| < |s|, t是s的一个前缀,同时t也是s的后缀,并且|t|最大化. 显然t是存在的,因为空串是满足要求的.t同时也是唯一的. 当s在输入字母l时,如果没有下一个状态,那么等价于t在输入字母l时的状态转移. 而关于t可以递归地构造.

int p = 0, q = 0;
sfx[1] = 1;
for (int i = 0; i < 7; ++i) if (trie[1][i])
{
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值