CF49E Common ancestor(dp+dp+dp)
纪念卡常把自己卡死的一次自闭模拟赛
QWQ
一开始看这个题,以为是个图论,仔细一想,貌似可以直接dp啊。
首先,因为规则只有从两个变为1个,貌似可以用类似区间\(dp\)的方式来\(check\)一段区间能不能合成某一个字母!
那我们定义\(f[i][j][k]\)表示第一个串,\([l,r]\)区间,是否可以合成\(k\)这个字母
然后转移的时候,枚举区间,枚举规则,枚举断点,满足\(f[l][k][p1]==1\)且\(f[k+1][r][p2]==1\) 才能使当前状态合法。
其中\(p1,p2\)表示当前规则的两个字母
for (int i=1;i<=n;i++) f[i][i][cc(s[i])]=1;
for (register int i=2;i<=n;++i)
for (register int l=1;l<=n-i+1;++l)
{
int r = l+i-1;
for (register int j=1;j<=26;++j)
{
for (register int p=1;p<=num[j];++p)
{
for (register int k=l;k<=r;++k)
{
f[l][r][j]=max(f[l][r][j],f[l][k][a[j][p].a]&f[k+1][r][a[j][p].b]);
if (f[l][r][j]) break;
}
if (f[l][r][j]) break;
}
}
}
同时定义\(g[l][r][k]\)数组表示第二个串区间\([l,r]\)能否合成k。处理和f类似。
统计答案的时候呢
还需要一个\(dp[i][j]\)表示第一个串的前i个字符和第二个串的前j个字符的最短公共祖先
那么,考虑枚举两个断点,两个串的后面两段能合成同一个字母,那么就可以从那个断点之前的状态转移过来
QWQ
详细直接看代码吧
memset(dp,127/3,sizeof(dp));
dp[0][0]=0;
for (register int i=1;i<=nn;++i)
{
for (register int k=1;k<=n;++k)
{
for (register int j=1;j<=i;++j)
for (register int p=1;p<=k;++p)
{
if (dp[j-1][p-1]==dp[maxn-3][maxn-3]) continue;
bool flag=false;
for (register int o=1;o<=26;o++)
if (g[j][i][o] && f[p][k][o]) flag=true;
if (flag) dp[i][k]=min(dp[i][k],dp[j-1][p-1]+1);
}
}
}
最后复杂度就是\(O(n^4*26)\)
我也不知道为啥能跑过啊
qwqwqwq
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define mk makr_pair
#define ll long long
#include<ctime>
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int maxn = 110;
struct Node{
int a,b;
};
Node a[maxn][maxn];
int num[maxn];
int f[maxn][maxn][maxn];
int g[maxn][maxn][maxn];
int n,m;
char s[maxn];
char ss[maxn];
int nn;
string ans;
int dp[maxn][maxn];
inline int cc(char c)
{
return c-'a'+1;
}
int main()
{
scanf("%s",s+1);
scanf("%s",ss+1);
s[0]=ss[0]='*';
n=strlen(s+1);
nn=strlen(ss+1);
m=read();
for (register int i=1;i<=m;++i)
{
char ymh[10];
scanf("%s",ymh+1);
int now = ymh[1]-'a'+1;
num[now]++;
a[now][num[now]].a = ymh[4]-'a'+1;
a[now][num[now]].b = ymh[5]-'a'+1;
}
for (int i=1;i<=n;i++) f[i][i][cc(s[i])]=1;
for (register int i=2;i<=n;++i)
for (register int l=1;l<=n-i+1;++l)
{
int r = l+i-1;
for (register int j=1;j<=26;++j)
{
for (register int p=1;p<=num[j];++p)
{
for (register int k=l;k<=r;++k)
{
f[l][r][j]=max(f[l][r][j],f[l][k][a[j][p].a]&f[k+1][r][a[j][p].b]);
if (f[l][r][j]) break;
}
if (f[l][r][j]) break;
}
}
}
for (int i=1;i<=nn;i++) g[i][i][cc(ss[i])]=1;
for (register int i=2;i<=nn;i++)
for (register int l=1;l<=nn-i+1;++l)
{
int r = l+i-1;
for (register int j=1;j<=26;++j)
{
for (register int p=1;p<=num[j];++p)
{
for (register int k=l;k<=r;++k)
{
g[l][r][j]=max(g[l][r][j],g[l][k][a[j][p].a]&g[k+1][r][a[j][p].b]);
if (g[l][r][j]) break;
}
if (g[l][r][j]) break;
}
}
}
memset(dp,127/3,sizeof(dp));
dp[0][0]=0;
for (register int i=1;i<=nn;++i)
{
for (register int k=1;k<=n;++k)
{
for (register int j=1;j<=i;++j)
for (register int p=1;p<=k;++p)
{
if (dp[j-1][p-1]==dp[maxn-3][maxn-3]) continue;
bool flag=false;
for (register int o=1;o<=26;o++)
if (g[j][i][o] && f[p][k][o]) flag=true;
if (flag) dp[i][k]=min(dp[i][k],dp[j-1][p-1]+1);
}
}
}
if(dp[nn][n]==dp[maxn-3][maxn-3]) dp[nn][n]=-1;
cout<<dp[nn][n]<<endl;
return 0;
}
CF49E Common ancestor(dp+dp+dp)的更多相关文章
- [PAT] 1143 Lowest Common Ancestor(30 分)
1143 Lowest Common Ancestor(30 分)The lowest common ancestor (LCA) of two nodes U and V in a tree is ...
- [CF49E]Common ancestor
[CF49E]Common ancestor 题目大意: 有两个由小写字母构成的字符串\(S\)和\(T(|S|,|T|\le50)\).另有\(n(n\le50)\)个形如\(a\to bc\)的信 ...
- 【Aizu2292】Common Palindromes(回文树)
[Aizu2292]Common Palindromes(回文树) 题面 Vjudge 神TMD日语 翻译: 给定两个字符串\(S,T\),询问\((i,j,k,l)\)这样的四元组个数 满足\(S[ ...
- PAT A1143 Lowest Common Ancestor (30 分)——二叉搜索树,lca
The lowest common ancestor (LCA) of two nodes U and V in a tree is the deepest node that has both U ...
- 【POJ3415】 Common Substrings(后缀数组|SAM)
Common Substrings Description A substring of a string T is defined as: T(i, k)=TiTi+1...Ti+k-1, 1≤i≤ ...
- POJ 1330 Nearest Common Ancestors(Targin求LCA)
传送门 Nearest Common Ancestors Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 26612 Ac ...
- [PAT] 1143 Lowest Common Ancestor(30 分)1145 Hashing - Average Search Time(25 分)
1145 Hashing - Average Search Time(25 分)The task of this problem is simple: insert a sequence of dis ...
- LeetCode 236. 二叉树的最近公共祖先(Lowest Common Ancestor of a Binary Tree)
题目描述 给定一棵二叉树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义: “对于有根树T的两个结点u.v,最近公共祖先表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. ...
- ACM学习历程—HDU 3092 Least common multiple(数论 && 动态规划 && 大数)
Description Partychen like to do mathematical problems. One day, when he was doing on a least common ...
随机推荐
- html调用swf的语句
<div style="width: 1000px; height: 202px; margin-left: auto; margin-right: auto"> &l ...
- Insights直播预告 | 多媒体管线服务,助您轻松进入“技术流”创新阵地
[导读] 随着各类音视频移动应用快速发展,短视频.线上直播等娱乐方式逐渐为大众所喜爱.优质的视听效果和交互体验,往往能吸引更多的用户.多媒体管线服务作为一个轻量级的多媒体开发框架,其跨平台.高性能的多 ...
- Appium问题解决方案(9)- Original error: Failed to launch Appium Settings app: Condition unmet after 5090 ms
背景 执行代码报错 解决方法 该问题并不常见,主要是手机操作系统的问题 程序无法无法自动打开appiumsettings,那么我们可以手动打开appiumsettings服务(程序没有界面,会出现打开 ...
- go语言游戏服务端开发(二)——网络通信
一.网络层 网络游戏客户端除了全局登录使用http请求外,一般通过socket长连接与服务端保持连接.go语言的net包提供网络socket长连接相关操作. 对于服务端,一般经历 Listen.Acc ...
- 从输入 URL 到展现页面的全过程
总体分为以下几个过程 DNS解析 TCP连接 发送HTTP请求 服务器处理请求并返回HTTP报文 浏览器解析渲染页面 连接结束 DNS解析 域名到ip地址转换 TCP连接 HTTP连接是基于TCP连接 ...
- JavaScript循环 — for、for/in、while、do/while
for 多次遍历代码块 const array = []for (var i = 0; i < 5; i++) { array.push(i)}console.log(array) // [0, ...
- php图片处理库
<?php namespace app\common\library; /** * include 'imagick.class.php'; $image = new lib_image_ima ...
- 机器学习——支持向量机SVM
前言 学习本章节前需要先学习: <机器学习--最优化问题:拉格朗日乘子法.KKT条件以及对偶问题> <机器学习--感知机> 1 摘要: 支持向量机(SVM)是一种二类分类模型, ...
- 机器学习——集成学习(Bagging、Boosting、Stacking)
1 前言 集成学习的思想是将若干个学习器(分类器&回归器)组合之后产生一个新学习器.弱分类器(weak learner)指那些分类准确率只稍微好于随机猜测的分类器(errorrate < ...
- Django学习day01随堂笔记
每日测验 """ 每日测验 1.你所知道的前端框架和实用插件有哪些,他们各有什么特点 2.使用bootstrap需要注意什么,常用的bootstrap样式有哪些 &quo ...