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. Linux基础 - crontab

    列出当前用户设置的定时任务 crontab -l 编辑定时任务 crontab -e 用法 m h dom mon dow * * * * * command 字段详解: *:any m: minut ...

  2. IntelliJ IDEA 去除IDE自动的参数名 提示功能

  3. 关于《C++ Templates》

    最近买了<C++ Templates>来看,书最开始部分阐述了关于此书的一些编程风格.本人感觉非常好,有些地方之前一直容易搞混,这里却讲述的很清楚.例如: 关于下面几种风格的代码: voi ...

  4. 【LOJ】#2587. 「APIO2018」铁人两项

    题解 学习了圆方树!(其实是复习了Tarjan求点双) 我又双叒叕忘记了tarjan点双一个最重要,最重要的事情! 就是--假如low[v] >= dfn[u],我们就找到了一个点双,开始建立方 ...

  5. 包装印刷行业裕同集团&易普优APS项目顺利验收!

    裕同集团&易普优APS项目于2017年7月启动,2018年1月上线,2018年5月初项目顺利验收!历时十个月,龙岗作为裕同集团APS的先锋试点项目,同时也是业务最复杂的分公司,双方联合团队紧密 ...

  6. pip-django-cms

    pip install django-el_pagination pip install django-ckeditor

  7. Tuning Optimization

    2017-02-22 在经过Trace的分析并重新优化之后 CPU: Intel(R) Xeon(R) CPU E5-2630 v2 @ 2.6GHz 24core 如上图,CPU使用率平均低于60% ...

  8. MyISAM InnoDB 区别(转载)

    MyISAM 和 InnoDB 讲解 InnoDB和MyISAM是许多人在使用MySQL时最常用的两个表类型,这两个表类型各有优劣,视具体应用而定.基本的差别为:MyISAM类型不支持事务处理等高级处 ...

  9. c++ 栈(顺序表)

    栈可以用顺序表(数组)也可以用链表来储存内容,本文采用顺序表(数组)来保存内部元素.代码如下:  1 #include <iostream> 2 using namespace std; ...

  10. CTF实验吧让我进去writeup

    初探题目 两个表单,我们用burp抓包试试 这时候我们发现Cookie值里有个很奇怪的值是source,这个单词有起源的意思,我们就可以猜测这个是判断权限的依据,让我们来修改其值为1,发送得到如下显示 ...