POJ1458 Common Subsequence(最长公共子序列LCS)

http://poj.org/problem?id=1458

题意:

给你两个字符串, 要你求出两个字符串的最长公共子序列长度.

分析:

本题不用输出子序列,非常easy,直接处理就可以.

首先令dp[i][j]==x表示A串的前i个字符和B串的前j个字符的最长公共子序列长度为x.

初始化: dp全为0.

状态转移:

IfA[i]==B[j] then

dp[i][j]= dp[i-1][j-1]+1

else

dp[i][j]= max( dp[i-1][j] , dp[i][j-1] )

上述公式: 当A[i]==B[j]时, A的第i个字符和B的第j个字符必定在A[1..i]和B[1..j]的最长公共子序列中, 所以dp[i][j]==dp[i-1][j-1]+1.

当A[i]!=B[j]时, A[i]和B[j]至少有一个是不可能在A[1..i]和B[1..j]的最长公共子序列中的, 所以dp[i][j] = max( dp[i-1][j] , dp[i][j-1] )

终于所求: dp[n][m].

AC代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=1000+5; int n,m;
int dp[maxn][maxn];
char s1[maxn],s2[maxn]; int main()
{
while(scanf("%s%s",s1,s2)==2)
{
n=strlen(s1);//s1串长度
m=strlen(s2);//s2串长度
memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(s1[i-1]==s2[j-1])
dp[i][j]=dp[i-1][j-1]+1;
else
dp[i][j]=max( dp[i-1][j] , dp[i][j-1] );
}
printf("%d\n",dp[n][m]);
}
return 0;
}

如今的问题是怎样按字典序输出全部的LCS串呢?

能够看到假设我们想求A[1..i]与B[1..j]的LCS, 那么当A[i]==B[j]时,

A[i](也是B[j]字符)这个字符是必定要被选的, 那么我们以下考虑A[1..i-1]和B[1..j-1]的LCS就可以. 我写了一个DFS逆序递推求出全部串的方法, 然后把串保存入set中, 就是按字典序排序且去重后的结果了.

DFS过程事实上就是一个逆序递推的过程. S字符数组保存了我们当前已经确定了LCS的末尾num个字符. 假设当前A[i]==B[j], 那么A[i]就是一个我们须要保存入S的字符数组. 假设A[i]!=B[j], 那么我们最多有两条不同的路继续前进. 每一个DFS都是一条可行路, 必定会找到一个可行的LCS.

只是上面方法会出现非常多反复的串, 所以效率比較低. 假设想提高效率还须要记录每一个字符出现的位置并做一定的优化.

代码例如以下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<set>
using namespace std;
const int maxn=100+5; int n,m;
int dp[maxn][maxn];
char s1[maxn],s2[maxn]; set<string> st;
char s[maxn];
char stmp[maxn];
int cnt;
//dfs从s1串的i位置和s2串的j位置開始逆序递推
//num是当前已经确定了LCS的末尾num个字符
//全部LCS保存到st中排序去重最后输出.
void dfs(int i,int j,int num)
{
if(num>=cnt)//已经找到了一个LCS
{
for(int i=num;i>=1;i--)
stmp[num-i]=s[i];
stmp[num]='\0'; string tmp(stmp);
st.insert(tmp);
return ;
}
if(s1[i]==s2[j])//该字符必选
{
s[++num]=s1[i];
dfs(i-1,j-1,num);
}
else //分情况讨论
{
if(dp[i-1][j]>dp[i][j-1])
dfs(i-1,j,num);
else if(dp[i-1][j]<dp[i][j-1])
dfs(i,j-1,num);
else
{
dfs(i-1,j,num);
dfs(i,j-1,num);
}
}
} int main()
{
while(scanf("%s%s",s1,s2)==2)
{
n=strlen(s1);//s1串长度
m=strlen(s2);//s2串长度
memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(s1[i-1]==s2[j-1])
dp[i][j]=dp[i-1][j-1]+1;
else
dp[i][j]=max( dp[i-1][j] , dp[i][j-1] );
}
printf("%d\n",dp[n][m]); cnt=dp[n][m];//cnt为LCS的长度 dfs(n-1,m-1,0); set<string>::iterator it;
for(it=st.begin(); it!=st.end(); ++it)
cout<<*it<<endl;
}
return 0;
}

POJ 1458 Common Subsequence(最长公共子序列LCS)的更多相关文章

  1. POJ 1458 Common Subsequence 最长公共子序列 LCS

    LCS #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> ...

  2. POJ 1458 Common Subsequence 最长公共子序列

    题目大意:求两个字符串的最长公共子序列 题目思路:dp[i][j] 表示第一个字符串前i位 和 第二个字符串前j位的最长公共子序列 #include<stdio.h> #include&l ...

  3. C++版 - Lintcode 77-Longest Common Subsequence最长公共子序列(LCS) - 题解

    版权声明:本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C++版 - L ...

  4. PKU 1458 Common Subsequence(最长公共子序列,dp,简单)

    题目 同:ZJU 1733,HDU 1159 #include <stdio.h> #include <string.h> #include <algorithm> ...

  5. lintcode 77.Longest Common Subsequence(最长公共子序列)、79. Longest Common Substring(最长公共子串)

    Longest Common Subsequence最长公共子序列: 每个dp位置表示的是第i.j个字母的最长公共子序列 class Solution { public: int findLength ...

  6. HDU 1159 Common Subsequence 最长公共子序列

    HDU 1159 Common Subsequence 最长公共子序列 题意 给你两个字符串,求出这两个字符串的最长公共子序列,这里的子序列不一定是连续的,只要满足前后关系就可以. 解题思路 这个当然 ...

  7. LCS(Longest Common Subsequence 最长公共子序列)

    最长公共子序列 英文缩写为LCS(Longest Common Subsequence).其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已 ...

  8. hdu 1159 Common Subsequence(最长公共子序列 DP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1159 Common Subsequence Time Limit: 2000/1000 MS (Jav ...

  9. LCS修改版(Longest Common Subsequence 最长公共子序列)

    题目描述 作为一名情报局特工,Nova君(2号)有着特殊的传达情报的技巧.为了避免被窃取情报,每次传达时,他都会发出两句旁人看来意义不明话,实际上暗号已经暗含其中.解密的方法很简单,分别从两句话里删掉 ...

随机推荐

  1. Python模块Pygame安装

    一.使用pip安装Python包 大多数较新的Python版本都自带pip,因此首先可检查系统是否已经安装了pip.在Python3中,pip有时被称为pip3. 1.在Linux和OS X系统中检查 ...

  2. LeetCode664. Strange Printer

    There is a strange printer with the following two special requirements: The printer can only print a ...

  3. Hive(八)Hive的Shell操作与压缩存储

    一.Hive的命令行 1.Hive支持的一些命令 Command Description quit Use quit or exit to leave the interactive shell. s ...

  4. Bootstrap Paginator分页插件使用示例

    最近做的asp.netMVC项目中需要对数据列表进行分类,这个本来就是基于bootstrap开发的后台,因此也就想着bootstrap是否有分页插件呢,或者说是基于jquery支持的分页功能,这样整体 ...

  5. USACO 5.5 Twofive

    TwofiveIOI 2001 In order to teach her young calvess the order of the letters in the alphabet, Bessie ...

  6. spring调用方法(接口和多个实现类的情况)

    以spring框架注入bean说明接口TestService 有2个实现类 TestServiceImp1 @Service("TestService1") ,TestServic ...

  7. Django实战(21):使用内置的Amin管理用户

    到目前为止,我们开发的所有功能都是匿名访问的,这显然不够安全.通常我们会要求注册的用户通过用户名和密码登录,只有登录后的用户才可以管理产品.套用专业的说法就是:第一步是认证,验证用户是否是他所宣称的那 ...

  8. Tomcat基于MSM+Memcached实现Session共享

    简述 上一篇文章,分别演示了session sticky 和 session cluster来实现会话保持的问题,但是它们缺点都不少,实际中用的很少,所以这篇文章我们还是通过Tomcat来演示一下实际 ...

  9. Java 中的国际化

    国际化 ,英文叫 internationalization 单词太长 ,又被简称为 i18n(取头取尾中间有18个字母)不经大声呼喊 ,这都行 !接着看什么是国际化 , 国际化是指让产品或是程序在无需 ...

  10. Kubernetes1.3:POD生命周期管理

    转:http://blog.csdn.net/horsefoot/article/details/52324830 (一)  核心概念 Pod是kubernetes中的核心概念,kubernetes对 ...