本文回顾了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可以递归地构造.
题意:给定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])
{