JZOJ 5167 【NOIP2017模拟6.26】下蛋爷
来源:互联网 发布:windows图形编程原理 编辑:程序博客网 时间:2024/04/28 08:04
题目大意:
有n个单词,有一个长度为m的文章,现在你先需要知道每个单词在文章内出现的次数。
现在一共进行k轮,每一轮有p的概率保留出现次数最小的那些单词(不保留就是把那些单词删掉)。
求n轮以后,每个单词保留下来的概率.
1<=n<=200,1<=单词长度<=20,1<=m<=10^6
题解:
分两个部分。
第一部分就直接上ac自动机,可以打up来优化。
ac自动机up优化:
up[x]表示x和x的fail链上的第一个是单词结尾的点。
这样查询的时候就会很快(贴瓷砖也有用的上)。
注意单词可能会有重复,单词结尾需要用前向星维护。
第二部分就是概率dp.
设f[i][j]表示第i轮,出现次数第j大的单词们活下来的概率(出现次数相同的算同一个)
f[i][j] = f[i - 1][j - 1] +f[i - 1][j] * p
Code:
#include<cstdio>#include<string>#include<cstring>#include<algorithm>#define fo(i, x, y) for(int i = x; i <= y; i ++)using namespace std;const int Maxn = 205, Maxm = 1000005;double p;char a[Maxn][25], s[Maxm];int n, ls, cc, ans[205], b[205], d[10000], next[10000][27], fail[10000], up[10000], tt;int final[10000], tot;struct edge { int to, next;}e[205];double f[1005][205], sum[1005];void link(int x, int y) { e[++ tot].next = final[x], e[tot].to = y, final[x] = tot; }void insert(int p, char *a) { int len = strlen(a + 1), k = 1; fo(i, 1, len) { if(!next[k][a[i] - 'a']) next[k][a[i] - 'a'] = ++ tt; k = next[k][a[i] - 'a']; } link(k, p);}void make_ac() { int l = 0, r = 0; d[++ r] = 1; while(l < r) { l ++; int x = d[l]; fo(i, 0, 25) { int y = next[x][i]; if(!y) continue; int j = fail[x]; while(j && !next[j][i]) j = fail[j]; if(next[j][i]) j = next[j][i]; fail[y] = j; if(!fail[y]) fail[y] = 1; up[y] = y; if(!final[y] && y != 1) up[y] = up[fail[y]]; d[++ r] = y; } }}void Init() { tt = 1; scanf("%d", &n); fo(i, 1, n) { scanf("%s", a[i] + 1); insert(i, a[i]); } make_ac(); scanf("%s", s + 1); ls = strlen(s + 1);}void Work() { int j = 1; fo(i, 1, ls) { while(j != 1 && !next[j][s[i] - 'a']) j = fail[j]; if(next[j][s[i] - 'a']) j = next[j][s[i] - 'a']; int z = up[j]; while(z) { for(int k = final[up[z]]; k; k = e[k].next) ans[e[k].to] ++; z = up[fail[z]]; } }}bool rank_b(int x, int y) { return ans[x] < ans[y]; }void End() { scanf("%lf", &p); scanf("%d", &cc); fo(i, 1, n) b[i] = i; sort(b + 1, b + n + 1, rank_b); fo(j, 2, n) f[1][j] = 1; f[1][1] = p; fo(i, 2, cc) { int k = 0; fo(j, 1, n) { if(j == 1 || ans[b[j]] != ans[b[j - 1]]) { k ++; f[i][k] = f[i - 1][k - 1] + (f[i - 1][k] - f[i - 1][k - 1]) * p; } } } int k = 0; fo(i, 1, n) { if(i != 1 && ans[b[i]] == ans[b[i - 1]]) sum[b[i]] = sum[b[i - 1]]; else k ++, sum[b[i]] = f[cc][k]; } fo(i, 1, n) printf("%.3lf ", sum[i]);}int main() { Init(); Work(); End();}
阅读全文
0 0
- JZOJ 5167 【NOIP2017模拟6.26】下蛋爷
- JZOJ 5167. 【NOIP2017模拟6.26】下蛋爷
- 【NOIP2017模拟6.26】下蛋爷
- JZOJ5167. 【NOIP2017模拟6.26】下蛋爷
- jzoj5167 【NOIP2017模拟6.26】下蛋爷 [ac自动机,概率递推]
- JZOJ 4910. 【NOIP2017模拟12.3】子串
- JZOJ 4910. 【NOIP2017模拟12.3】子串
- JZOJ 5230. 【NOIP2017模拟A组模拟8.5】队伍统计
- JZOJ 5230. 【NOIP2017模拟A组模拟8.5】队伍统计
- JZOJ 4909. 【NOIP2017模拟12.3】李电下棋
- JZOJ 4911. 【NOIP2017模拟12.3】人生的叹息
- JZOJ 4909 【NOIP2017模拟12.3】李龟下棋
- JZOJ 4911 【NOIP2017模拟12.3】人生的叹息
- JZOJ 4919. 【NOIP2017提高组模拟12.10】神炎皇
- JZOJ 4921. 【NOIP2017提高组模拟12.10】幻魔皇
- JZOJ 4919.【NOIP2017提高组模拟12.10】神炎皇
- JZOJ 4919. 【NOIP2017提高组模拟12.10】神炎皇
- 【JZOJ 4922】【NOIP2017提高组模拟12.17】环
- 三位水仙花数
- Eclipse出现some characters cannot be mapped using GBK
- 数据挖掘学习(二)-数据仓库
- java 引参和传值参
- 【zabbix教程四】——zabbix3.0监控磁盘IO与自定义模板
- JZOJ 5167 【NOIP2017模拟6.26】下蛋爷
- 使用C#更改打印机驱动打印属性设置
- ThreadPoolExcutor(线程池)
- td-idf的理解
- C语言基础一之预备知识(计算机结构组成、计算机系统组成、进制、原码反码补码)
- /etc/sysctl.conf 立即生效
- 【zabbix教程六】——自定义item和trigger当内存不足10%时触发报警
- rz sz命令
- Nginx 配置简述