题目链接:戳我

30分暴力。。。。暴力提取子序列即可qwqwq

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
#define MAXN 5010
using namespace std;
int lena,lenb,n,ans,cnt;
int dp[MAXN][MAXN];
char a[MAXN],b[MAXN],cur[MAXN],pre[MAXN];
map<string,int>sum;
inline void init(int pos)
{
if(cnt==n)
{
string s;
for(int i=1;i<=cnt;i++) s+=pre[i];
sum[s]++;
return;
}
if(pos>=lenb) return;
for(int i=pos+1;i<=lenb;i++)
{
pre[++cnt]=b[i];
init(i);
cnt--;
}
}
inline void solve(int pos)
{
if(cnt==n)
{
string s;
for(int i=1;i<=cnt;i++) s+=cur[i];
ans+=sum[s];
return;
}
if(pos>=lena) return;
for(int i=pos+1;i<=lena;i++)
{
cur[++cnt]=a[i];
solve(i);
cnt--;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
freopen("ce.out","w",stdout);
#endif
scanf("%s%s",a+1,b+1);
lena=strlen(a+1)-1;
lenb=strlen(b+1)-1;
for(int i=1;i<=lena;i++)
{
for(int j=1;j<=lenb;j++)
{
dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
if(a[i]==b[j]) dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1);
}
}
n=dp[lena][lenb];
init(0);
cnt=0;
solve(0);
printf("%d\n%d\n",n,ans);
return 0;
}

考虑满分算法?题解的话强烈安利Flash_hu dalao的题解

第一问很好做,也就是f[i][j]表示第一个序列到第i位,第二个序列到第j位,最长的公共子序列的长度。f[i][j]可以从f[i-1][j]和f[i][j-1]转移过来,如果a[i]==b[j]的话还可以从f[i-1][j-1]+1转移过来。

对于第二问,我们设sum[i][j]表示第一个序列到第i位,第二个序列到第j位,最长公共子序列长度为f[i][j]的子序列个数。显然如果f[i-1][j]f[i][j]的话,我们是可以从sum[i-1][j]转移过来的,f[i][j-1]f[i][j]同理。额外的,如果f[i-1][j-1]+1==f[i][j]时,我们还可以累加sum[i-1][j-1]的答案。

就这样就结束了吗?不对,你会发现W掉了。为什么呢?

这是因为如果当f[i-1][j-1]==f[i][j]的时候,sum[i-1][j-1]的值对sum[i-1][j]和sum[i][j-1]各贡献了一次。而我们累加到sum[i][j]的时候相当于重算了一次,所以还要记得减去哦qwqwq

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define MAXN 5010
#define mod 100000000
using namespace std;
int lena,lenb;
int f[2][MAXN],sum[2][MAXN];
char a[MAXN],b[MAXN];
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
freopen("ce.out","w",stdout);
#endif
scanf("%s%s",a+1,b+1);
lena=strlen(a+1)-1,lenb=strlen(b+1)-1;
for(int i=0;i<=lenb;i++) sum[0][i]=1;
sum[1][0]=1;
for(int i=1;i<=lena;i++)
{
for(int j=1;j<=lenb;j++)
{
sum[1][j]=0;
f[1][j]=max(f[1][j-1],f[0][j]);
if(a[i]==b[j]) f[1][j]=max(f[1][j],f[0][j-1]+1);
if(a[i]==b[j]&&f[0][j-1]+1==f[1][j]) sum[1][j]+=(sum[1][j]+sum[0][j-1])%mod;
if(f[1][j-1]==f[1][j]) sum[1][j]=(sum[1][j]+sum[1][j-1])%mod;
if(f[0][j]==f[1][j]) sum[1][j]=(sum[1][j]+sum[0][j])%mod;
if(a[i]!=b[j]&&f[0][j-1]==f[1][j]) sum[1][j]=(sum[1][j]+mod-sum[0][j-1])%mod;
}
swap(f[0],f[1]),swap(sum[0],sum[1]);
}
printf("%d\n%d\n",f[0][lenb],sum[0][lenb]);
return 0;
}

HAOI2010 最长公共子序列的更多相关文章

  1. [BZOJ2423][HAOI2010]最长公共子序列

    [BZOJ2423][HAOI2010]最长公共子序列 试题描述 字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x ...

  2. 【BZOJ2423】[HAOI2010]最长公共子序列 DP

    [BZOJ2423][HAOI2010]最长公共子序列 Description 字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字 ...

  3. 2021.12.10 P2516 [HAOI2010]最长公共子序列(动态规划+滚动数组)

    2021.12.10 P2516 [HAOI2010]最长公共子序列(动态规划+滚动数组) https://www.luogu.com.cn/problem/P2516 题意: 给定字符串 \(S\) ...

  4. bzoj:2423: [HAOI2010]最长公共子序列

    Description 字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0, ...

  5. [HAOI2010]最长公共子序列(LCS+dp计数)

    字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X=“x0,x1,…,xm-1”,序列Y=“y0,y1,…,yk-1”是X ...

  6. 洛谷P2516 [HAOI2010]最长公共子序列(LCS,最短路)

    洛谷题目传送门 一进来就看到一个多月前秒了此题的ysn和YCB%%% 最长公共子序列的\(O(n^2)\)的求解,Dalao们想必都很熟悉了吧!不过蒟蒻突然发现,用网格图貌似可以很轻松地理解这个东东? ...

  7. LG2516 【[HAOI2010]最长公共子序列】

    前言 感觉这几篇仅有的题解都没说清楚,并且有些还是错的,我再发一篇吧. 分析 首先lcs(最长公共子序列)肯定是板子.但这题要求我们不能光记lcs是怎么打的,因为没这部分分,并且另外一个方程的转移要用 ...

  8. bzoj 2423: [HAOI2010]最长公共子序列【dp+计数】

    设f[i][j]为a序列前i个字符和b序列前j个字符的最长公共子序列,转移很好说就是f[i][j]=max(f[i-1][j],f[i][j-1],f[i-1][j-1]+(a[i]==b[j])) ...

  9. 洛谷 P2516 [HAOI2010]最长公共子序列

    题目传送门 解题思路: 第一问要求最长公共子序列,直接套模板就好了. 第二问要求数量,ans[i][j]表示第一个字符串前i个字符,第二个字符串前j个字符的最长公共子序列的数量 如果f[i][j]是由 ...

随机推荐

  1. angularjs 出现 “Possibly unhandled rejection: cancel ”错误

    Try adding this to your config. I had a similar is once and this workaround did the trick. app.confi ...

  2. python:窗口化和制作图形

    #圆 from tkinter import * canvas = Canvas(width=800, height=600, bg='yellow')#声明窗口属性 canvas.pack(expa ...

  3. 数字1的ASCII值是多少

    ASCII表是计算机将字符转为数字存储的一张转换表.因此,只有字符才有ASCII值,数字是没有的. 答案:数字1没有ASCII值,数字1在计算机中就是按数值1存储的. 字符1的ASCII值是 49

  4. 4.2 最邻近规则分类(K-Nearest Neighbor)KNN算法应用

    1 数据集介绍:   虹膜     150个实例   萼片长度,萼片宽度,花瓣长度,花瓣宽度 (sepal length, sepal width, petal length and petal wi ...

  5. VMWare中三种网络连接模式的区别

    VMWare中有桥接.NAT.host-only三种网络连接模式,在搭建伪分布式集群时,需要对集群的网络连接进行配置,而这一操作的前提是理解这三种网络模式的区别. 参考以下两篇文章可以更好的理解: V ...

  6. 解决Eclipse编辑JavaScript时卡的问题

    eclipse在开发JavaEE项目时容易卡,特别是在编辑JavaScript时,经过网上各种搜索,综合整理一下,对自己的eclipse设置之后,结果不在出现卡的问题了. 原文地址:http://bl ...

  7. maven filter插件只替换了部分变量问题

    maven filter简介 maven的resources插件,有一个filter的作用,能够在打包的时候,从特定文件里读取key-value对,替换配置文件中的占位符变量.很多线上线下有不同环境的 ...

  8. LoadRunner11学习记录二 -- 进行cookie模拟

    1.LoadRunner录制打开一个网页的脚本,会生成脚本夹杂迅雷,迅雷看看,百度等链接地址,这是因为ie打开之后会加载未禁用的加载项.需要把相关的加载项禁用掉. 禁用ie加载项步骤,工具--管理加载 ...

  9. p4980 polya定理

    传送门 分析 orz ymh 代码 #include<iostream> #include<cstdio> #include<cstring> #include&l ...

  10. Luogu 4726 【模板】多项式指数函数

    补补补…… 这个题的解法让我认识到了泰勒展开的美妙之处. 泰勒展开 泰勒展开就是用一个多项式型的函数去逼近一个难以准确描述的函数. 有公式 $$f(x)\approx g(x) = g(x_0) + ...