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

时间:2021-09-19 23:29:04

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&gt ...

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

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

  3. C&plus;&plus;版 - Lintcode 77-Longest Common Subsequence最长公共子序列&lpar;LCS&rpar; - 题解

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

  4. PKU 1458 Common Subsequence&lpar;最长公共子序列,dp,简单&rpar;

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

  5. lintcode 77&period;Longest Common Subsequence&lpar;最长公共子序列&rpar;、79&period; Longest Common Substring&lpar;最长公共子串&rpar;

    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&lpar;最长公共子序列 DP&rpar;

    题目链接: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. 【Linux】AWK入门

    什么是AWK AWK是一种用于处理文本的编程语言工具,一个模式匹配程序.一个典型的示例是将数据转换成格式化的报告. 在命令行输入如下awk命令: awk -F":" '{ prin ...

  2. HTML中添加背景音乐

    <audio controls="controls" height="100" width="100"> <source ...

  3. PHP扩展开发及内核应用

    目录中汉字部分代表已经翻译完成的章节,带链接的表示已经发布的,未待链接的表示正在校正即将发布的. PHP的生命周期 让我们从SAPI开始 PHP的启动与终止 PHP的生命周期 线程安全 小结 PHP变 ...

  4. 用JavaScript实现的选项卡

    Codes wins arguments! <!DOCTYPE html> <html> <head> <meta charset="utf-8&q ...

  5. Git 操作的一些场景

    1. 某些不需要的文件/文件夹,如:/build 之类,在添加对应的gitignore之前Push了,导致每次编译都会产生新的文件 解决方法:直接删掉不需要的文件/文件夹,然后push gitigno ...

  6. 第五篇 Replication:事务复制-How it works

    本篇文章是SQL Server Replication系列的第五篇,详细内容请参考原文. 这一系列包含SQL Server事务复制和合并复制的详细内容,从理解基本术语和设置复制的方法,到描述它是如何工 ...

  7. Permutation Sequence &lbrack;LeetCode&rsqb;

    The set [1,2,3,…,n] contains a total of n! unique permutations. By listing and labeling all of the p ...

  8. 《RESTful Web Services》第一章 使用统一接口

    序言 HTTP是一种应用层协议.SOAP和一些Ajax Web框架都将HTTP作为一种传输信息的协议,难以充分利用HTTP层的基础设施. 1.2 如何保持交互的可见性     可见性是HTTP的一个核 ...

  9. C&num; string LastIndexOf&lpar;&rpar;

    IndexOf(“FindText",start,len) 中的Start和Len是从左往右数的 LastIndexOf(“FindText",start,len)中的则是从右往左 ...

  10. java&period;util&period;concurrent-------TimeUnit

    java.util.concurrent并发库是JDK1.5新增的,其作者是Doug Lea ,此人是个BOSS级别的天才人物了.有了他提供的类库,使得我们对多线程并发.锁有了很大的帮助,减少了并发难 ...