B Boring Problem

题意:
给出n≤100n \le 100n≤100个长度为m≤100m \le 100m≤100的串TiT_iTi​和一个串RRR,对每个RRR的前缀,每次在其末尾以PiP_iPi​的概率添加字符i≤k≤26i \le k \le 26i≤k≤26,当生成的字符串SSS中存在一个TiT_iTi​为SSS的子串时停止,求生成的字符串的期望长度。
题解:
首先有个暴力做法:
对TiT_iTi​建立AC自动机,设tri,jtr_{i,j}tri,j​表示从节点iii添加字符jjj到达的节点,EiE_iEi​表示从节点iii开始,停止时末尾添加字符个数的期望。
最后用字符串RRR跑一边AC自动机计算答案。
在AC自动机上,对于所有叶子节点,Eleaf=0E_{leaf} = 0Eleaf​=0;对于所有非叶子节点uuu,转移为Eu=1+∑i=1kPiEtru,iE_u=1 +\sum_{i=1}^kP_iE_{tr_{u,i}}Eu​=1+∑i=1k​Pi​Etru,i​​;注意到转移有环,需要高斯消元,O(nm)O(nm)O(nm)个未知数和等式,复杂度O(n3m3)O(n^3m^3)O(n3m3)。
将未知数个数降为O(n)O(n)O(n):
设EquationiEquation_iEquationi​表示Ei=EquationiE_i=Equation_iEi​=Equationi​,其中EquationiEquation_iEquationi​由常数和O(n)O(n)O(n)个未知数组成。
1.初始化根节点ErootE_{root}Eroot​为一个未知数,当前未知数总数为1。
2.按深度递增遍历AC自动机。
3.设当前深度为depdepdep,深度≤dep\le dep≤dep的节点的EquationiEquation_iEquationi​都已知;
对于节点uuu,若是叶子结点,则将Eu=0=EquationuE_u=0=Equation_uEu​=0=Equationu​扔进方程组;
否则,设sonsonson为节点u的所有原字典树的儿子,设sonsonson的大小为szszsz,将其中sz−1sz-1sz−1个EvE_vEv​设为新的未知数,此时Equationv=EvEquation_v=E_vEquationv​=Ev​;并根据上述转移移项可得剩下一个儿子的EquationvEquation_vEquationv​,即Equationv=Equationu−1−∑i=1kPiEquationtru,i[tru,i≠v]PvEquation_v=\frac{Equation_u-1-\sum_{i=1}^kP_iEquation_{tr_{u,i}}[tr_{u,i≠v}]}{P_v}Equationv​=Pv​Equationu​−1−∑i=1k​Pi​Equationtru,i​​[tru,i​=v​]​。
转移复杂度O(n2mk)O(n^2mk)O(n2mk),具体实现可参考代码。
设叶子的个数为nnn,等式的个数为叶子的个数nnn,未知数的个数为111(根)+n−1n-1n−1(分叉的个数)=n=n=n。
高斯消元复杂度O(n3)O(n^3)O(n3)。

解释一下样例1:

AC自动机如上图,叶子节点的出边就不画了,P1=P2=1/2P_1=P_2=1/2P1​=P2​=1/2。
红绿边为fail边,黑边为字典树的原边。
过程如下:

  1. 初始化Equation0=E0Equation_0=E_0Equation0​=E0​,当前未知数E0E_0E0​。
  2. 来到深度为000的000号根节点,其son={1,3}son=\{1,3\}son={1,3},增加未知数E3E_3E3​,Equation3=E3Equation_3=E_3Equation3​=E3​,根据转移,Equation1=Equation0−1−P2Equation3P1=2E0−E3−2Equation_1=\frac{Equation_0-1-P_2Equation_3}{P_1}=2E_0-E_3-2Equation1​=P1​Equation0​−1−P2​Equation3​​=2E0​−E3​−2;当前未知数E0,E3E_0,E_3E0​,E3​。
  3. 来到深度为111的111号节点,其son={2}son=\{2\}son={2},(3不是字典树上的儿子),根据转移,Equation2=Equation1−1−P2Equation3P1=4E0−3E3−6Equation_2=\frac{Equation_1-1-P_2Equation_3}{P_1}=4E_0-3E_3-6Equation2​=P1​Equation1​−1−P2​Equation3​​=4E0​−3E3​−6;当前未知数E0,E3E_0,E_3E0​,E3​。
  4. 来到深度为111的222号节点,其son={4}son=\{4\}son={4},根据转移,Equation4=Equation3−1−P1Equation1P2=−2E0+3E3Equation_4=\frac{Equation_3-1-P_1Equation_1}{P_2}=-2E_0+3E_3Equation4​=P2​Equation3​−1−P1​Equation1​​=−2E0​+3E3​;当前未知数E0,E3E_0,E_3E0​,E3​。
  5. 来到2号叶子节点,根据0=Equation20=Equation_20=Equation2​,有 4E0−3E3=64E_0-3E_3=64E0​−3E3​=6。
  6. 来到4号叶子节点,根据0=Equation40=Equation_40=Equation4​,有−2E0+3E3=0-2E_0+3E_3=0−2E0​+3E3​=0。
  7. 根据这两个等式解出E0,E3E_0,E_3E0​,E3​,即可解出所有EiE_iEi​。

Code:

#include<bits/stdc++.h>using namespace std;
typedef long long ll;
const int N = 1e4 + 10;
constexpr int mod = 1e9 + 7;ll power(ll a, ll b) {ll res = 1;while (b) {if (b & 1)res = res * a % mod;a = a * a % mod;b >>= 1;}return res;
}void add(int &a, int b) { a = (a + b) % mod; }vector<int> Gauss(vector<vector<int>> a) {//a[1,n][1,n+1] a[i][n+1]为常数int n = a.size() - 1;for (int y = 1; y <= n; y++) {int mx = y;for (int x = y; x <= n; x++)if (a[x][y] > a[mx][y])mx = x;int ik = power(a[mx][y], mod - 2);for (int i = y; i <= n + 1; i++)a[mx][i] = (ll) a[mx][i] * ik % mod;for (int x = 1; x <= n; x++)if (x != mx && a[x][y]) {int k = a[x][y];for (int i = y; i <= n + 1; i++) {add(a[x][i], mod - (ll) a[mx][i] * k % mod);}}swap(a[y], a[mx]);}vector<int> res(n + 1);for (int i = 1; i <= n; i++)res[i] = a[i][n + 1];return res;
}vector<int> operator+(vector<int> a, vector<int> b) {int n = max(a.size(), b.size());a.resize(n), b.resize(n);for (int i = 0; i < n; i++)add(a[i], b[i]);return a;
}vector<int> operator-(vector<int> a, vector<int> b) {int n = max(a.size(), b.size());a.resize(n), b.resize(n);for (int i = 0; i < n; i++)add(a[i], mod - b[i]);return a;
}vector<int> operator*(vector<int> a, ll b) {b = (b % mod + mod) % mod;for (auto &I:a)I = I * b % mod;return a;
}int n, m, k;
vector<int> Equation[N];
int E[N];
int p[26];struct AC {int tr[N][26], tot, dep[N];int fail[N];bool key[N];int insert(char s[]) {int u = 0;for (int i = 1; s[i]; i++) {int c = s[i] - 'a';if (!tr[u][c])tr[u][c] = ++tot;u = tr[u][c];if (key[u])break;dep[u] = i;}key[u] = 1;return u;}void build() {queue<int> q;for (int i = 0; i < k; i++)if (tr[0][i])q.push(tr[0][i]);while (!q.empty()) {int u = q.front();q.pop();for (int i = 0; i < k; i++) {if (tr[u][i]) {fail[tr[u][i]] = tr[fail[u]][i], q.push(tr[u][i]);} elsetr[u][i] = tr[fail[u]][i];}}}void calc_e() {queue<int> q;int tot_unknown = 0;//当前未知数个数//Equation[u][0] 表示常数 Equation[u][1,tot_unknown]表示未知数的系数// 初始化根节点E_root 为未知数q.push(0);Equation[0].assign({0, 1});tot_unknown++;vector<vector<int>> a(1);//等式组while (!q.empty()) {int u = q.front();q.pop();if (key[u]) {a.push_back(Equation[u]);continue;//one equation}vector<int> son;//字典树上的儿子int p_son = -1;//第0个儿子的字符期望for (int i = 0; i < k; i++) {if (dep[tr[u][i]] > dep[u]) {son.push_back(tr[u][i]);q.push(tr[u][i]);if (p_son == -1)p_son = p[i];}}for (int i = 1; i < son.size(); i++) {//新增sz-1 个未知数Equation[son[i]].resize(tot_unknown + 1);Equation[son[i]].push_back(1);tot_unknown++;}//求son[0]的Equationint v = son[0];Equation[v] = Equation[u];add(Equation[v][0], mod - 1);for (int i = 0; i < k; i++)if (tr[u][i] != v) {Equation[v] = Equation[v] - Equation[tr[u][i]] * p[i];}Equation[v] = Equation[v] * power(p_son, mod - 2);}for (auto &I:a) {I.resize(tot_unknown + 2);I.back() = (mod - I.front()) % mod;}vector<int> res = Gauss(a);for (int i = 0; i <= tot; i++) {for (int j = 1; j < Equation[i].size(); j++)add(E[i], (ll) res[j] * Equation[i][j] % mod);add(E[i], Equation[i][0]);//加上常数}}void print_ans(char *s) {int u = 0;bool sub=0;for (int i = 1; s[i]; i++) {u = tr[u][s[i] - 'a'];if(key[u])sub=1;if(sub)cout<<i<<"\n";else cout << (E[u] + i) % mod << "\n";}}
} ac;char s[N];int main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin >> n >> m >> k;for (int i = 0; i < k; i++)cin >> p[i], p[i] = p[i] * power(100, mod - 2) % mod;for (int i = 0; i < n; i++) {cin >> s + 1;ac.insert(s);}ac.build();ac.calc_e();cin >> s + 1;ac.print_ans(s);
}

2020 ACM-ICPC澳门区域赛 B Boring Problem 主元法相关推荐

  1. 2020年 ICPC 亚洲区域赛(上海)G-Fibonacci

    ICPC 亚洲区域赛(上海) G-Fibonacci 题目 斐波那契数列为1,1,2,3,5,8,13,21,- 可以看到,这个数列有以下特点: 奇,奇,偶,奇,奇,偶- 当 xxx 与 yyy 相乘 ...

  2. 2018年 ACM/ICPC亚洲区域赛 青岛赛区现场赛 比赛总结

    首先祝贺自己收获了ACM生涯中的第二枚铜牌. 首先吐槽一下中石油: 周六早上来到中国石油大学,连个志愿者小姐姐都没看到.(但是看到了女装大佬).报完到之后发现教练少了一张午餐券(要不要这么粗心).为了 ...

  3. 第43届ACM icpc亚洲区域赛焦作站感想

    青岛痛失银牌,焦作又是铜牌一枚,现在想想,前面三个水题,我的原因太大了,老是犯各种zz小错误,明明能秒,却花了大量时间debug,导致三个小时才签完到,最后一个小时,F题的bfs没出来,B题也没出来, ...

  4. 2016 年 ACM/ICPC 青岛区域赛 Problem C Pocky

    昨晚乱入学弟的训练赛,想了一下这个题.推导的过程中,加深了对公理化的概率论理解.$\newcommand{\d}{\mathop{}\!\mathrm{d}}$ 解法一 考虑 $ d < L$ ...

  5. 2019年安徽大学ACM/ICPC实验室新生赛题解

    本文仅作个人收藏学习使用 题目及解析来源牛客竞赛网 //作者:王清楚 //链接:https://ac.nowcoder.com/discuss/351408?type=101&order=0& ...

  6. icpc西部区域赛_ICPC西部区域赛捷报传来!

    ICPC西部区域赛(新疆赛区)圆满结束软件学子斩获佳绩 2020年10月31日,由新疆大学信息科学与工程学院(网络空间安全学院)承办的ICPC国际大学生程序设计竞赛2020年西部区域赛(新疆赛区)圆满 ...

  7. 2019 ACM - ICPC 上海网络赛 E. Counting Sequences II (指数型生成函数)

    繁凡出品的全新系列:解题报告系列 -- 超高质量算法题单,配套我写的超高质量题解和代码,题目难度不一定按照题号排序,我会在每道题后面加上题目难度指数(1∼51 \sim 51∼5),以模板题难度 11 ...

  8. icpc西部区域赛_信息学子在ACMICPC 2020中国(西部)大学生程序设计竞赛中喜获佳绩...

    2020年10月31日ACM-ICPC 2020中国(西部)大学生程序设计竞赛圆满结束,信息科学与工程学院组织51支队伍参赛,荣获2枚金牌,4枚银牌,17枚铜牌,成绩优异. 国际大学生程序设计竞赛(简 ...

  9. 2019年安徽大学ACM/ICPC实验室新生赛

    题目链接 A.素数分布函数\pi (n)π(n)表示小于或等于n的素数的数目.例如\pi (10)=4π(10)=4(2,3,5,7是素数).这个函数涉及到许多高等数论的内容,甚至和黎曼猜想挂钩,目前 ...

最新文章

  1. C#让windows程序只运行一次
  2. windows加固方案
  3. const数组,strstr,strstr,
  4. 美好生活从撸好代码开始
  5. 代码实现从键盘接收一个字符串, 程序对其中所有字符进行排序,例如键盘输入: helloitcast程序打印:acehillostt...
  6. 台式计算机总是重启,台式电脑经常自动重启怎么修复
  7. 详解5G:关键能力、关键技术、应用场景、网络架构、经济影响
  8. JavaScript高级程序设计33.pdf
  9. 三维点云学习(2)中-Kd-tree (k-dimensional tree)
  10. [转] PHP:自己动手制作伪原创程序
  11. TeamViewer开机自启动实现在远程使用时重启远程计算机
  12. NISP一级考试题库
  13. Java数组对象排序
  14. 车载以太网测试之实锤-基于电阻噪声和高斯噪声的SQI测试对比
  15. 2020年10月24日=996 程序员节日快乐
  16. 自考学习记录 课程代码03708《中国近代史纲要》1
  17. 功率谱和频谱的区别、联系(自用)
  18. PS A11选区和选框工具
  19. 【单片机】辉光管时钟系列<一>--单片机最小系统
  20. 锐界机器人_钱江机器人/海峰机器人/锐界科技彰显“装配”技术实力

热门文章

  1. 【雨滴桌面】发布两个自己写的DOCK,可隐藏的应用栏,一个在侧边,一个在底部
  2. 基于Matlab对费根鲍姆常数和费根鲍姆图的一些算法分析
  3. QMUI全局样式配置
  4. 灰色关联分析法(GRA)-C++实现
  5. 圣斗士星矢服务器维护时间,《圣斗士星矢》9月29日更新维护公告
  6. 给你的 ART-Pi (STM32H7) 降降温
  7. 解决传导干扰八大绝招
  8. jquery ajax post请求下载文件
  9. Leave-one-out——留一法
  10. 一招搞定GitHub下载加速!