今日得分:2+10+4
(今天的T1和T3是原题,然而我并没做过,惨遭毒瘤。。。)(不过好像大家也没太写)
(话说好像真正实现起来并没有太过毒瘤)
T1
题目大意:给你一个长度为L的字符串s0,字符集大小为2n,q次操作,A操作表示在第f个字符串s[f]后面接上一个字符x,得到一个最新的s,Q操作询问第f个字符串s[f],目前有一个字符串t已经匹配到了l,每次随机在t后面添加一个字符,期望添加多少字符使得s[f]能够作为t的子串出现mod998244353,强制在线。n,q,L<=3e5。
题解:
定义题目所求为E(s,l),通过生成函数可以证明以下式子(具体证明参考CTSC2006歌唱王国):
注意到[s[1…i]=s[n-i+1…n]]等价于1-i是s的border,于是我们考虑KMP。由于每次增加一个字符,我们可以看成在原来的结构上添加一个新节点,从而动态构建操作树。通过倍增算法可以记录每一个点的next[i]的深度以及对应链上第next[i]+1个字符,这样的话除去KMP部分的复杂度是O(NlogN)。至于KMP部分,我们考虑我们寻找next指针时,其实质相当于构建出每个点的KMP自动机,每次添加一个新字符,先通过原串的自动机找到next节点,把它的所有转移边拷贝过来,并更改一条对next节点本身的转移边,用主席树即可做到O(logn)复杂度转移。所以总时间复杂度是O(NlogN)的。
(话说为啥我写的O(nlogn)还没O(nlog^2n)跑得快啊,哭了)
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<vector>
#include<cmath>
using namespace std;
inline int re_ad()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'