POJ 1625 Censored!(AC自动机+DP)
来源:互联网 发布:java 读取apk版本号 编辑:程序博客网 时间:2024/05/16 15:14
POJ 1625 Censored!(AC自动机+DP)
http://poj.org/problem?id=1625
题意:
给你由特定N个字符组成的P个模板和长度M,问你由这特定N个字符组成的长为M的文本串不包含任意一个模板有多少种情况?M<=50
分析:
由于M<=50,所以直接用DP做,不用矩阵幂算.本题很类似UVA11468:
http://blog.csdn.net/u013480600/article/details/23294375
我们令d[i][j]=x表示当前在i号节点,还有j步要走且不经过后缀单词节点的情况总数为x.
初值d[i][0]=1. i为非单词节点
d[i][j] = sum(d[k][j-1])其中从i可以走到k,且i和k节点都不是后缀单词节点.
最后我们所求为d[0][m]。(用本解法可以使用记忆话搜索,因为我们很容易知道d[i][j]的所有依赖项d[k][j-1])
或者可以这么推(程序中用的就是该方式):
令d[i][j]=x表示当前在i点,已经走过了j距离的情况总数为x.
d[i][j]=sum(d[k][j-1])从k可以走到i,且k和i都是非单词节点.
初值为d[0][0]=1.其他都为0,然后用滚动数组递推即可。(用本节点只能使用递推刷新求DP,因为我们无法知道d[i][j]的所有依赖项d[k][j-1])
AC代码:
#include<iostream>#include<queue>#include<map>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>using namespace std;const int maxnode=100+20;int sigma_size;//后面读入struct AC_Automata{ int ch[maxnode][50+20]; int match[maxnode]; int f[maxnode]; map<char ,int> mp; int sz; void init() { sz=1; memset(ch[0],0,sizeof(ch[0])); match[0]=f[0]=0; mp.clear(); } void insert(char *s) { int n=strlen(s),u=0; for(int i=0;i<n;i++) { int id=mp[s[i]]; if(ch[u][id]==0) { ch[u][id]=sz; memset(ch[sz],0,sizeof(ch[sz])); match[sz++]=0; } u=ch[u][id]; } match[u]=1; } void getFail() { f[0]=0; queue<int> q; for(int i=0;i<sigma_size;i++) { int u=ch[0][i]; if(u) { f[u]=0; q.push(u); } } while(!q.empty()) { int r=q.front();q.pop(); for(int i=0;i<sigma_size;i++) { int u=ch[r][i]; if(!u){ ch[r][i]=ch[f[r]][i]; continue; } q.push(u); int v=f[r]; while(v && ch[v][i]==0) v=f[v]; f[u]=ch[v][i]; match[u] |= match[f[u]]; } } }};AC_Automata ac;int dp[100+10][50+10][100];//dp[i][j]是一个最大长度为100的大数void add(int *a,int *b)//大数相加,a[0]表示的是个位,a[1]是十位{ int c=0;//进位 for(int i=0;i<100;i++) { int s=a[i]+b[i]+c; a[i]=s%10; c=s/10; }}int main(){ int n,m,p; char str[50+20]; while(scanf("%d%d%d",&n,&m,&p)==3) { sigma_size=n; ac.init(); scanf("%s",str); for(int i=0;i<n;i++) ac.mp[str[i]]=i; while(p--) { scanf("%s",str); ac.insert(str); } ac.getFail(); memset(dp,0,sizeof(dp)); dp[0][0][0]=1;//起点 for(int k=0;k<m;k++) { for(int i=0;i<ac.sz;i++) if(ac.match[i]==0) for(int j=0;j<sigma_size;j++) if(ac.match[ac.ch[i][j]]==0) add(dp[ac.ch[i][j]][k+1],dp[i][k]); } int ans[100]; memset(ans,0,sizeof(ans));//记得初始化 for(int i=0;i<ac.sz;i++)if(ac.match[i]==0) add(ans,dp[i][m]); int i=99; for(;i>=1;i--) if(ans[i]) break; for(;i>=0;i--) printf("%d",ans[i]); putchar('\n'); } return 0;}
阅读全文
0 0
- poj 1625 Censored!//AC自动机+DP+大数
- POJ--1625[Censored!] AC自动机+DP+高精度
- POJ 1625 Censored【AC自动机+DP+大数】
- POJ 1625 Censored!(AC自动机+DP)
- 【AC自动机+DP+大数】 POJ 1625 Censored!
- poj 1625 Censored!(AC自动机+DP+高精度)
- POJ 1625 Censored!(AC自动机,DP)
- poj 1625 Censored! (ac自动机+dp)
- poj 1625 Censored! AC自动机+dp+高精度
- [AC自动机+dp+高精度] poj 1625 Censored!
- POJ 1625 Censored(AC自动机+dp)
- POJ 1625 Censored! AC自动机+DP+高精度 *
- POJ 1625 Censored!(AC自动机+DP)
- poj 1625 Censored! 【AC自动机 + DP + 强力大数模版】
- poj 1625 Censored! AC自动机+DP +高精度 + C艹 + java
- POJ 1625 Censored! AC自动机 简单DP 高精度
- POJ 1625 Censored! (AC自动机+DP+高精度,5级)
- poj 1625 Censored!(AC自动机+DP+高精)
- 一步一步教你如何安装elasticsearch-head插件
- Android_补间动画
- OSGI(2)_创建OSGi Hello World工程
- bzoj4653 [Noi2016]区间
- python处理命令行参数
- POJ 1625 Censored!(AC自动机+DP)
- 腾讯云海量社交网络业务下的DevOps架构应用实践
- PHP实现 记录网站访问量
- maven安装插件的配置
- 开源ESB-ServiceMix服务总线
- 信号在android源码/external/pppd 源码项目中的应用解读分析
- <c:forEach>详解
- 微信公众号中信息推送出现中文乱码的问题的思考
- android开发中常见的问题