ACM-ICPC 南昌网络赛F题 Megumi With String

题目描述

给一个长度为\(l\)的字符串\(S\),和关于\(x\)的\(k\)次多项式\(G[x]\).当一个字符串\(str\)是S的子串时,定义\(str\)的\(value\)值为\(G[length(str)]\),否则\(value=0\)。一个字符串的\(power\)值定义为其所有子串的\(value\)之和。每次向\(S\)末尾添加一个字符,重复\(m\)次。求每次添加字符后,一个长度为\(n\)的随机串\(T\)的\(power\)期望值。每个测试点\(Q\)组数据

  • 出现在不同位置的相同串视为\(T\)的不同子串
  • 多项式的次数不大于\(50\)

\(\sum l,\sum m,\sum k\leq 3\times10^5\)

题目链接

题解

  • 由于串是随机的,所以不适合以特定串为研究对象。因此考虑指定长度的子串的贡献。长度为\(i\)的串的贡献正比于\(S\)中长度为\(i\)的本质不同的子串个数。由于要在线添加字符,所以使用后缀自动机维护以上信息。

使用后缀自动机维护本质不同的子串个数有两种方法:

  1. 由于从源点沿转移边到达的点所经过的路径都是一个子串,所以\(f[i]=\sum _{i\rightarrow j}(f[j] + 1)\),\(f[i]\)表示从i出发的路径个数,答案为\(f[\empty]\)
  2. SAM上每一个结点都代表一个等价类,该节点包含了长度为\((longest(fa[i]),longest(i)]\)的子串,而每一个节点包含的子串都不相同。

显然,用方法2可以更方便地在插入字符时就更新\((longest(fa[i]),longest(i)]\)的子串个数变化。

\(S\)的最终长度为\(l+m\),其中长度大于\(n\)的子串不会产生贡献。所以我们处理的子串长度范围是\([1,min(l+m,n)]\),设\(N=min(l+m,n)\)

  • \(T\)的总个数为\(26^n\)

  • 长度为\(i\)的子串出现的总次数为\((n-i+1)\cdot 26^{n-i+1}\)(出现在不同位置*周围不同字符)。所以长度为\(i\)的子串对\(power\)的贡献为\(cnt_i\cdot (n-i+1)\cdot 26^{n-i+1}\cdot G[i]\)

\(cnt_i\)表示\(S\)中长度为\(i\)本质不同的子串个数

则\(E_{power}(T)=\frac{1}{26^n}\sum_{i=1}^{min(l+m,n)}cnt_i\cdot (n-i+1)\cdot 26^{n-i+1}\cdot G[i]\)

令\(H[i]=(n-i+1)\cdot 26^{n-i+1}\cdot G[i]\)

  • 由于\(H[i]\)只与\(i\)有关,因此可以预处理\(0\sim N\)的\(H\)值

因为每次只修改连续的区间,修改只有加一操作,而且求和的范围为固定的整个区间,因此可以预处理\(H[i]\)的前缀和,每次\(O(1)\)修改对应\(len\)区间的贡献,然后直接输出\(ans\)

if (fa.longest < n) ans = (0ll + ans + G[min(n, now.longest)] + P - G[fa.longest]) % P;

处理细节

  1. 处理多组数据注意后缀自动机的初始化
void init(int nn) {
memset(am[1].ch, 0, sizeof(am[0].ch));
las = cnt = 1;
n = nn;
} //insert()
memset(am[cnt].ch, 0, sizeof(am[0].ch));
  1. 单个字符的读入——来自C语言的gank

让我误以为是读不进去,换了各种方法。最后发现其实是后缀自动机的构造函数写错才导致的TLE

把代码改的面目全非

for (i = 0; i < m; ++i)	{
ch = getchar();
if (islower(ch))
AM.insert(ch);
else {
tt++;
i--;
if (tt > 4e5)
return 0;
continue;
}
printf("%d\n", (int)(1ll * ans * inv % P));
}

最后全部改回去了。

AC代码

#include <iostream>
#include <cstring> using namespace std;
const int maxn = 2e5 + 1, P = 998244353, v26 = 729486258, sigma_size = 26; //v26=inv(26)
int G[maxn + 1], N, a[51], ans;
char S[100001]; int fexp(int x, int n) {
int ret = 1;
while (n) {
if (n & 1) ret = 1ll * ret * x % P;
x = 1ll * x * x % P;
n >>= 1;
}
return ret;
}
void getG(int len, int n, int K) {
int n26 = fexp(26, n);
G[0] = 0;
for (int i = 1; i <= len; ++i) {
int ans = 0, x = 1;
n26 = 1ll * n26 * v26 % P;
for (register int j = 0; j <= K; ++j) {
ans = (1ll * x * a[j] % P + ans) % P;
x = 1ll * x * i % P;
}
G[i] = ans;
G[i] = (1ll * G[i] * (n - i + 1) %P * n26 %P + G[i - 1]) % P;
}
return;
} struct SAM {
struct Node {
int longest, fa;
int ch[sigma_size];
Node() {
memset(ch, 0, sizeof(ch));
longest = 0;
}
}am[maxn << 1];
int las = 1, cnt = 1, n;
void init(int nn) {
memset(am[1].ch, 0, sizeof(am[0].ch));
las = cnt = 1;
n = nn;
}
void insert(int c) {
int p = las, np = ++cnt;
memset(am[np].ch, 0, sizeof(am[0].ch));
las = np;
am[np].longest = am[p].longest + 1;
for (; p && !am[p].ch[c]; p = am[p].fa) am[p].ch[c] = np;
if (!p) am[np].fa = 1;
else {
int q = am[p].ch[c];
if (am[q].longest == am[p].longest + 1) am[np].fa = q;
else {
int nq = ++cnt;
am[nq] = am[q];
am[np].fa = nq;
am[nq].longest = am[p].longest + 1;
am[q].fa = nq;
for (; p && am[p].ch[c] == q; p = am[p].fa) am[p].ch[c] = nq;
}
} if (am[am[np].fa].longest < n)
ans = (0ll + ans + G[min(n, am[np].longest)] + P - G[am[am[np].fa].longest]) % P; }
}AM;
int main() {
int Q, l, m, K, i, n, inv;
char ch;
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
cin>>Q;
while (Q--) {
cin>>l>>K>>n>>m;
N = min(l + m, n);
ans = 0;
AM.init(n);
inv = fexp(fexp(26, n), P - 2); cin>>S;
for (i = 0; i <= K; ++i)
cin>>a[i];
getG(N, n, K);
for (int j = 0; j < l; ++j) AM.insert(S[j]);
cout<<(1ll * ans * inv % P)<<endl; for (i = 0; i < m; ++i) {
cin>>ch;
AM.insert(ch);
cout<<(1ll * ans * inv % P)<<endl;
}
}
return 0;
}

ACM-ICPC 2019南昌网络赛F题 Megumi With String的更多相关文章

  1. ACM-ICPC 2019南昌网络赛I题 Yukino With Subinterval

    ACM-ICPC 2019南昌网络赛I题 Yukino With Subinterval 题目大意:给一个长度为n,值域为[1, n]的序列{a},要求支持m次操作: 单点修改 1 pos val 询 ...

  2. [2019上海网络赛F题]Rhyme scheme

    题目链接 题意,求出合法的长度为n的字典序第k小字符串,合法的定义为除了最后一位,每一位的取值范围为'A'到'A'+pos-1,而最后一位的取值范围'A'到当前字符串最大值+1. 队友tql,Orz ...

  3. 2019南昌网络赛I:Yukino With Subinterval(CDQ) (树状数组套主席树)

    题意:询问区间有多少个连续的段,而且这段的颜色在[L,R]才算贡献,每段贡献是1. 有单点修改和区间查询. 思路:46min交了第一发树套树,T了. 稍加优化多交几次就过了. 不难想到,除了L这个点, ...

  4. ICPC 2019 徐州网络赛

    ICPC 2019 徐州网络赛 比赛时间:2019.9.7 比赛链接:The Preliminary Contest for ICPC Asia Xuzhou 2019 赛后的经验总结 // 比赛完才 ...

  5. Magic Master(2019年南昌网络赛E题+约瑟夫环)

    目录 题目链接 题意 思路 代码 题目链接 传送门 题意 初始时你有\(n\)张牌(按顺序摆放),每一次操作你将顶端的牌拿出,然后按顺序将上面的\(m\)张牌放到底部. 思路 首先我们发下拿走\(1\ ...

  6. 2013 ACM/ICPC 长春网络赛F题

    题意:两个人轮流说数字,第一个人可以说区间[1~k]中的一个,之后每次每人都可以说一个比前一个人所说数字大一点的数字,相邻两次数字只差在区间[1~k].谁先>=N,谁输.问最后是第一个人赢还是第 ...

  7. 2013 ACM/ICPC 南京网络赛F题

    题意:给出一个4×4的点阵,连接相邻点可以构成一个九宫格,每个小格边长为1.从没有边的点阵开始,两人轮流向点阵中加边,如果加入的边构成了新的边长为1的小正方形,则加边的人得分.构成几个得几分,最终完成 ...

  8. 2019 ICPC南昌网络赛 B题

    英雄灭火问题忽略了一点丫 一个超级源点的事情,需要考虑周全丫 2 #include<cstdio> #include<cstring> #include<queue> ...

  9. 2019 ICPC南京网络赛 F题 Greedy Sequence(贪心+递推)

    计蒜客题目链接:https://nanti.jisuanke.com/t/41303 题目:给你一个序列a,你可以从其中选取元素,构建n个串,每个串的长度为n,构造的si串要满足以下条件, 1. si ...

随机推荐

  1. Cracking the coding interview目录及资料收集

    前言 <Cracking the coding interview>是一本被许多人极力推荐的程序员面试书籍, 详情可见:http://www.careercup.com/book. 第六版 ...

  2. ztree点击节点实现选中/取消复选框

    效果 代码 在js中初始化tree时 设置复选框操作只影响子节点 复选框事件,想怎么处理就怎么处理

  3. Java集合框架——Set接口

    第三阶段 JAVA常见对象的学习 集合框架--Set接口 List集合的特点是有序的,可重复的,是不是存在这一种无序,且能保证元素唯一的集合呢?(HashSet )这就涉及到我们今天所要讲的Set集合 ...

  4. [Python3 填坑] 004 关于八进制

    目录 1. print( 坑的信息 ) 2. 开始填坑 2.1 问题的由来 2.2 问题的解决 2.2.1 先说结论 2.2.2 八进制的用途 2.2.3 少废话,上例子 1. print( 坑的信息 ...

  5. 剑指offer29:最小的k个数

    1 题目描述 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 2 思路和方法,C++核心代码 2.1 sort()函数,ve ...

  6. ASP.NET跨平台、分布式技术架构技术栈概览 (迄今为止最全的.NET技术栈)

    今天有个学技术的小兄弟问我,现在这么多的技术我要学哪个?我说你根据岗位来学,学好了哪一门都可以在社会上立足,如今已经早已不是我们当年学习IT时候那么单纯了,给他讲了很多,发现现在的技术栈变得层次复杂且 ...

  7. mydumper,myloader原理及实战

    mydumper 特性 (1)多线程备份(和mysqlpump的多线程不同,mysqlpump多线程备份的粒度是表,mydumper多线程备份的粒度是行,这对于备份大表特别有用)(2)因为是多线程逻辑 ...

  8. 植物大战僵尸:寻找召唤僵尸关键CALL

    实验目标:通过遍历寻找召唤僵尸的CALL,通过调用CALL出现自定义的僵尸,加速僵尸的出现. 僵尸CALL的遍历技巧: 我们可以通过僵尸出现在屏幕中的个数来遍历寻找僵尸出现的CALL 首先打开CE-& ...

  9. 怎样初始化XMLHttpRequest实例对象xhr

    xhr.open() 接收5个参数, 用于初始化一个http请求, 它接收5个参数: 1. method: 请求类型; 2. url: 请求的url; 3. async: 是否为异步, 默认为true ...

  10. java lesson09总结

    package Super; public class SuperTest {  String color;  // public SuperTest(String color) {this.colo ...