题目链接:点击查看

题目大意:给出一个匹配串 sss,现在问模式串 ttt 的期望得分。其中假设匹配串在模式串中的出现次数为 xxx,那么将得到 2x2^x2x 的分数

题目分析:涉及到了期望一开始还以为是概率,后来发现其实就是个计数问题

题目实际让我们操作的就是,枚举 5n5^n5n 种字符串,然后对于每种字符串统计匹配串 sss 的出现次数,注意这里的出现次数并不能说是最多或最少的出现次数,先将贡献的式子转换一下:
2x=(...((1)∗2)∗2)∗2...)∗22^x=(...((1)*2)*2)*2...)*22x=(...((1)∗2)∗2)∗2...)∗2

假设枚举的字符串 ttt 中可以匹配一次 sss ,那么只需要将匹配次数相应的乘以二就可以实现上面的公式了,关于期望的话最后只需要除以 5n5^n5n 就好啦

现在问题转换为了字符串计数问题,我的第一反应就是 ACACAC 自动机裸题啊,直接挂上模板过了,简单讲一下思路,就是将匹配串扔进 ACACAC 自动机里,dpi,jdp_{i,j}dpi,j​ 代表到了字符串 ttt 的第 iii 个位置时,在自动机里匹配的状态为 jjj 的方案数,转移的话就是枚举第 i+1i+1i+1 的字符记为 chchch,方程就是:
dpi+1,trie[j][ch]+=dp[i][j]dp_{i+1,trie[j][ch]}+=dp[i][j]dpi+1,trie[j][ch]​+=dp[i][j]

非常简单的过了,不过后续意识到是不是有点大材小用了?因为这个题目只有一个匹配串啊,为什么不直接用 KMPKMPKMP 去写呢?然后就用 KMPKMPKMP 也写了一发。。不过有一说一,对于失配状态转移的 dpdpdp,以后还是用自动机来写吧,因为相比之下 KMPKMPKMP 的细节略多

代码:
AC自动机

// Problem: Connie
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/17148/D
// Memory Limit: 1048576 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<list>
#include<unordered_map>
#define lowbit(x) x&-x
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{T f=1;x=0;char ch=getchar();while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();x*=f;
}
template<typename T>
inline void write(T x)
{if(x<0){x=~(x-1);putchar('-');}if(x>9)write(x/10);putchar(x%10+'0');
}
const int inf=0x3f3f3f3f;
const int N=110;
const int mod=998244353;
const char str[]="conie";
char s[N];
LL dp[N][N];
int fail[N],flag[N],trie[N][26],cnt;
int newnode() {cnt++;for(int i=0;i<26;i++) {trie[cnt][i]=0;}flag[cnt]=false;return cnt;
}
void insert_word()
{int len=strlen(s);int pos=0;for(int i=0;i<len;i++){int to=s[i]-'a';if(!trie[pos][to])trie[pos][to]=newnode();pos=trie[pos][to];}flag[pos]=true;
}
void getfail()
{queue<int>q;for(int i=0;i<26;i++){if(trie[0][i]){fail[trie[0][i]]=0;q.push(trie[0][i]);}}while(!q.empty()){int cur=q.front();q.pop();for(int i=0;i<26;i++){if(trie[cur][i]){fail[trie[cur][i]]=trie[fail[cur]][i];q.push(trie[cur][i]);}elsetrie[cur][i]=trie[fail[cur]][i];}}
}
LL q_pow(LL a,LL b) {LL ans=1;while(b) {if(b&1) {ans=ans*a%mod;}a=a*a%mod;b>>=1;}return ans;
}
int main()
{#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);int n,m;read(n),read(m);scanf("%s",s);insert_word();getfail();dp[0][0]=1;for(int i=0;i<n;i++) {for(int j=0;j<=cnt;j++) {for(int k=0;k<5;k++) {int nj=trie[j][str[k]-'a'];dp[i+1][nj]=(dp[i+1][nj]+dp[i][j]*(flag[nj]?2:1))%mod;}}}LL ans=0;for(int i=0;i<=cnt;i++) {ans=(ans+dp[n][i])%mod;}ans=(ans*q_pow(q_pow(5,n),mod-2))%mod;cout<<ans<<endl;return 0;
}

KMP:

// Problem: Connie
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/17148/D
// Memory Limit: 1048576 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<list>
#include<unordered_map>
#define lowbit(x) x&-x
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{T f=1;x=0;char ch=getchar();while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();x*=f;
}
template<typename T>
inline void write(T x)
{if(x<0){x=~(x-1);putchar('-');}if(x>9)write(x/10);putchar(x%10+'0');
}
const int inf=0x3f3f3f3f;
const int N=1e6+100;
const int mod=998244353;
const char str[]="conie";
char s[N];
int nt[N];
void get_next() {int len=strlen(s+1);nt[1]=0;for(int i=2,j=0;i<=len;i++) {while(j!=0&&s[j+1]!=s[i]) {j=nt[j];}if(s[j+1]==s[i]) {j++;}nt[i]=j;}
}
LL dp[110][110];
LL q_pow(LL a,LL b) {LL ans=1;while(b) {if(b&1) {ans=ans*a%mod;}a=a*a%mod;b>>=1;}return ans;
}
int main()
{#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);int n,m;read(n),read(m);scanf("%s",s+1);get_next();dp[0][0]=1;for(int i=0;i<n;i++) {for(int j=0;j<=m;j++) {for(int k=0;k<5;k++) {char ch=str[k];int p=j;while(p!=0&&ch!=s[p+1]) {p=nt[p];}if(ch==s[p+1]) {p++;}dp[i+1][p]=(dp[i+1][p]+dp[i][j]*(p==m?2:1))%mod;}}}LL ans=0;for(int i=0;i<=m;i++) {ans=(ans+dp[n][i])%mod;}ans=(ans*q_pow(q_pow(5,n),mod-2))%mod;cout<<ans<<endl;return 0;
}

牛客 - Connie(AC自动机+dp/KMP+dp)相关推荐

  1. 牛客练习赛26B 烟花 (概率DP)

    链接:https://ac.nowcoder.com/acm/contest/180/B 来源:牛客网 烟花 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言5 ...

  2. 牛客练习赛60C 操作集锦(DP)

    题目链接 链接:https://ac.nowcoder.com/acm/contest/4853/C 来源:牛客网 题目描述 有一款自走棋有26种操作,每种操作我们都用a,b,c,d,-,x,y,z的 ...

  3. 牛客网-xinjun与阴阳师(背包DP)

    链接:https://ac.nowcoder.com/acm/problem/14602 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K,其他语言2621 ...

  4. hdu 3962(AC自动机+矩阵优化dp)

    转载标记处:http://blog.csdn.net/woshi250hua/article/details/7599472 题目大意:给定m个DNA病毒序列,求碱基构成的长度为n且含有两个以上DNA ...

  5. HDU - 2825 Wireless Password (AC自动机 + 状压dp)

    题目链接 题意 求至少包含KKK个给定字符串长度为NNN的字符串 思路 把所有可能的字符串建AC自动机,遍历所有节点dp[i][j][k]dp[i][j][k]dp[i][j][k] 表示以节点jjj ...

  6. HDU - 3247 Resource Archiver(AC自动机+状压dp+bfs)

    题目链接:点击查看 题目大意:给出 n 个目标串和 m 个病毒串,要求构造出一个长度最短的,且包含全部 n 个目标串,但是不能包含任意一个病毒串的01字符串,输出其最短长度 题目分析:比较综合的一道题 ...

  7. HDU - 3341 Lost's revenge(AC自动机+状压dp)

    题目链接:点击查看 题目大意:给出 n 个模式串,最后给出一个匹配串,问如何重新排列匹配串,可以使得匹配串尽可能多的匹配模式串 题目分析:因为是模式串和匹配串的匹配,所以考虑AC自动机,因为数据范围比 ...

  8. HDU - 2825 Wireless Password(AC自动机+状压dp)

    题目链接:点击查看 题目大意:给出 m 个匹配串,问长度为 n 的字符串中,至少包含 k 个匹配串(可重叠)的字符串有多少个 题目分析:考虑到n,m,k都特别小,所以可以先用AC自动机将状态关系转移出 ...

  9. hdu 6086 Rikka with String(AC自动机+状压dp)

    题目链接:hdu 6086 Rikka with String 题意: 给你n个只含01的串,和一个长度L,现在让你构造出满足s[i]≠s[|s|−i+1] for all i∈[1,|s|] ,长度 ...

最新文章

  1. python多重继承
  2. leetcode算法题--二分查找
  3. 表白c语言程序设计,C语言编程学习打造表白神器:亲爱的让我们相爱在一起
  4. 图片序列化和反序列化成图片文件(代码)
  5. 【Vue】—项目的目录结构介绍
  6. (十七)Activitivi5之组任务分配
  7. oracle非延迟约束,Oracle可延迟约束Deferable的使用
  8. 启动关闭HadoopSpark历史服务
  9. SNMPv3对安全威胁的分类
  10. Java 性能测试的四项原则
  11. JavaScript的陷阱[转]
  12. navicat中看sql执行计划
  13. 【English】十二、英语句子种类,陈述句、疑问句、祈使句、感叹句
  14. 航空客运订票系统C语言程序设计,航空客运订票系统的程序算法?
  15. Microsoft Visio 2013在安装过程中出错的一种解决方案
  16. rsa java模数_使用模数和指数的RSA解密
  17. 方舟:生存进化官服和私服区别
  18. 易语言取计算机的ip,易语言怎样取IP物理地址
  19. ASP.NET图书管理系统简单实现步骤
  20. 国内计算机类期刊SCI/EI检索

热门文章

  1. 如何使用 Go 语言搭建企业级高并发服务器?
  2. matlab匿名函数求导,Matlab中的匿名函数的使用
  3. php使用redis持久化,redis如何持久化
  4. html同时执行多个ajax,Ajax方法详解以及多个Ajax并发执行
  5. MySQL高级 - 复制 - 原理
  6. 关于DubboMain启动的真相
  7. Zookeeper基于Java访问-权限
  8. 使用redis实现订阅功能
  9. 单例设计模式-容器单例
  10. java 怎么清除画布_HTML5 Canvas 清除画布