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. 提高班第三周周记(中秋第三天)
  2. 职称计算机证是继续教育的内容吗,豆腐网教你一分钟弄懂继续教育学时认定表及上传注意事项~...
  3. 9个数 横竖和相等 php,[境遇之数]横竖都是伤,不如一起扛(Ep9-12集剧评)
  4. 有关军事人机混合智能的再再思考
  5. java中的乐活锁_(转)[乐活]别抱怨了,Shit happens!
  6. android布局的属性大全,Android布局属性大全
  7. 【人工智能作业及答案】什么叫智能?什么叫人工智能?人工智能科学体系大致分哪几个层次?
  8. 如何让ios app支持32位和64位?
  9. oracle查看数据库是否恢复成功_记一次解决docker下oracle数据库故障事例
  10. LIS(最长上升子序列)的 DP 与 (贪心+二分) 两种解法
  11. ajax中xmlhttp.readyState==4 xmlhttp.status==200 是什么意思
  12. Python实现AI贪吃蛇
  13. 设计一个递归算法释放二叉树bt中的所有结点(二叉树采用二叉链表存储结构)
  14. linux ftp下载geo,GEO数据下载及处理详细过程
  15. unity shader shaderLab 手册
  16. DCDC电源纹波测试
  17. git的使用——reset
  18. 关于python浮点数类型错误的是_关于Python的数字类型,以下选项中描述错误的是...
  19. String类字符串习题作业
  20. 拼多多,为老妈打开了“新世界”的大门

热门文章

  1. 记录一下蚂蚁金服的电话面试
  2. 4千块小米新旗舰发布:首发骁龙888,雷军:AI性能盖过华为苹果
  3. 解决mac系统向日葵远控无法被远程控制问题(白屏)
  4. 汇总:Linux下文件操作接口
  5. 阿里云飞天加速高校计划续领六个月
  6. 怎么测试t470p性能软件,ThinkPad T470p值得买吗?ThinkPad T470p商务本全面详细评测图解...
  7. 浏览器必备灵魂插件谷歌浏览器翻译,番剧解除区域限制/全能启动器/
  8. 建立自己的kindle书库,并实现公网访问
  9. 下拉框的二级联动和回显
  10. 正点原子stm32MP157 点亮LED程序