纪念卡常把自己卡死的一次自闭模拟赛

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)的更多相关文章

  1. [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 ...

  2. [CF49E]Common ancestor

    [CF49E]Common ancestor 题目大意: 有两个由小写字母构成的字符串\(S\)和\(T(|S|,|T|\le50)\).另有\(n(n\le50)\)个形如\(a\to bc\)的信 ...

  3. 【Aizu2292】Common Palindromes(回文树)

    [Aizu2292]Common Palindromes(回文树) 题面 Vjudge 神TMD日语 翻译: 给定两个字符串\(S,T\),询问\((i,j,k,l)\)这样的四元组个数 满足\(S[ ...

  4. 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 ...

  5. 【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≤ ...

  6. POJ 1330 Nearest Common Ancestors(Targin求LCA)

    传送门 Nearest Common Ancestors Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 26612   Ac ...

  7. [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 ...

  8. LeetCode 236. 二叉树的最近公共祖先(Lowest Common Ancestor of a Binary Tree)

    题目描述 给定一棵二叉树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义: “对于有根树T的两个结点u.v,最近公共祖先表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. ...

  9. ACM学习历程—HDU 3092 Least common multiple(数论 && 动态规划 && 大数)

    Description Partychen like to do mathematical problems. One day, when he was doing on a least common ...

随机推荐

  1. C# - Timer 实现跑马灯

  2. 快速使用 Docker 上手 Sentry-CLI - 玩转 Source Maps 使用 (create-react-app)

    系列 快速使用 Docker 上手 Sentry-CLI - 创建版本 入门 使用 sentry-cli 上传 source maps 时,您需要设置构建系统以创建版本(release)并上传与该版本 ...

  3. group by分组查询

    有如下数据: 一个简单的分组查询的案例 按照部门编号deptno分组,统计每个部门的平均工资. select deptno,avg(sal) avgs from emp group by deptno ...

  4. JavaScript高级程序设计学习笔记之事件

    1.事件流 事件流描述的是从页面中接收事件的顺序. 事件冒泡 IE的事件流叫做事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播 ...

  5. Ajax技术---核心XMLHttpRequest对象

    Ajax 的全称是Asynchronous JavaScript and XML,其中,Asynchronous 是异步的意思,它有别于传统web开发中采用的同步的方式. (一)ajax技术的意义 我 ...

  6. 分布式系列-分布式ID

    一.数据库自增(单实例) 1.方案描述 基于数据库自增ID(auto_increment)利用其来充当分布式ID.实现方式就是用一张表来充当ID生成器,当我们需要ID时,向表中插入一条记录返回主键ID ...

  7. struts框架返回json数据

    设置返回result类型为json格式 <package name="cn.konngo.action" namespace="/" extends=&q ...

  8. 使用vbs调用excel中的宏

    使用vbs打开excel文件,并且传递参数调用excel中的macro,自动化完成excel文件的制作. Set oExcel = createobject("Excel.Applicati ...

  9. 再见了,我的散装研发管理平台;再见了,4台ECS!

    周末的时候,收到好几个云服务器临近过期的通知短信,准备续个费,居然都要大几千!因为这几个都是以前低价抢购的,掐指一算,如果都续费的话,要蚕食好多利润!作为一名自己养活自己的独立开发者,节省成本是必备技 ...

  10. TCP可靠传输原理

    停止等待协议 "停止等待"就是发送方在发送完一个分组后停止发送,等待接收方的确认后再继续发送. 超时重传 发送方在等待一定时间后如果还没有收到接收方的确认,此时发送方将认定分组没有 ...