转自:http://www.cppblog.com/varg-vikernes/archive/2010/09/27/127866.html

1)首先按照常规的方法求出最长公共子序列的长度
也就是用O(MN)的那个动态规划,结果放在二维数组dp里
dp[i][j] = { 字串a的1~i部分与字串b的1~j部分的最长公共子序列的长度 }
2)求辅助数组
last1[i][j] = { 到下标i为止,字符j在字串a中最后一次出现的下标 }
last2[i][j] = { 到下标i为止,字符j在字串b中最后一次出现的下标 }
3)枚举最长公共字串的每一个字符
从最后一个字符开始枚举
比如说现在枚举最后一个字符是'C'的情况。
那么 'CDCD' 与 'FUCKC' 这两个字串。
一共有 (0, 2) (0, 4)  (2, 2)  (2. 4) 这四种可能。
很明显前三个是可以舍弃的,因为第四个优于前三个,为后续的枚举提供了更大的空间。
last数组正好是用来做这个的。
4)排序输出
代码里用了stl的set。

 // File Name: 1934.cpp
// Author: Missa_Chen
// Created Time: 2013年07月07日 星期日 20时21分33秒 #include <iostream>
#include <string>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <cstdlib>
#include <vector>
#include <time.h> using namespace std;
const int maxn = ;
int dp[maxn][maxn];
int last1[maxn][], last2[maxn][];
set <string> ans;
char tmp[maxn];
void dfs(int s1, int s2, int len)
{
if (len <= )
{
ans.insert(tmp);
return ;
}
if (s1 > && s2 > )
{
for (int i = ; i < ; ++i)
{
int t1 = last1[s1][i];
int t2 = last2[s2][i];
if (dp[t1][t2] == len)
{
tmp[len - ] = 'a' + i;
dfs(t1 - , t2 - , len - );
}
}
}
return ;
}
void LCS(string s1, string s2)
{
memset(dp, , sizeof(dp));
for (int i = ; i <= s1.size(); ++i)
{
for (int j = ; j <= s2.size(); ++j)
{
if (s1[i - ] == s2[j - ])
dp[i][j] = dp[i - ][j - ] + ;
else dp[i][j] = max(dp[i - ][j], dp[i][j - ]);
}
}
}
void solve(string s1, string s2)
{
memset(last1, , sizeof(last1));
memset(last2, , sizeof(last2));
for (int i = ; i <= s1.size(); ++i)
{
for (int j = ; j < ; ++j)
last1[i][j] = last1[i - ][j];
last1[i][s1[i - ] - 'a'] = i;
}
for (int i = ; i <= s2.size(); ++i)
{
for (int j = ; j < ; ++j)
last2[i][j] = last2[i - ][j];
last2[i][s2[i - ] - 'a'] = i;
}
tmp[dp[s1.size()][s2.size()]] = '\0';
dfs(s1.size(), s2.size(), dp[s1.size()][s2.size()]);
for (set <string> :: iterator it = ans.begin(); it != ans.end(); ++it)
cout <<*it<<endl;
}
int main()
{
string s1, s2;
while (cin >> s1 >> s2)
{
LCS(s1, s2);
solve(s1, s2);
}
return ;
}

poj 1934(LCS)的更多相关文章

  1. [POJ 1934] Trip

    [题目链接] http://poj.org/problem?id=1934 [算法] 先用dp求出LCS,然后搜索即可,注意加上一些剪枝 [代码] #include <algorithm> ...

  2. POJ 2250(LCS最长公共子序列)

    compromise Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u   Descri ...

  3. poj 2264(LCS)

    Advanced Fruits Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2158   Accepted: 1066   ...

  4. POJ 2217 LCS(后缀数组)

    Secretary Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1655   Accepted: 671 Descript ...

  5. $2019$ 暑期刷题记录1:(算法竞赛DP练习)

    $ 2019 $ 暑期刷题记录: $ POJ~1952~~BUY~LOW, BUY~LOWER: $ (复杂度优化) 题目大意:统计可重序列中最长上升子序列的方案数. 题目很直接的说明了所求为 $ L ...

  6. POJ 1159 回文串-LCS

    题目链接:http://poj.org/problem?id=1159 题意:给定一个长度为N的字符串.问你最少要添加多少个字符才能使它变成回文串. 思路:最少要添加的字符个数=原串长度-原串最长回文 ...

  7. LCS POJ 1458 Common Subsequence

    题目传送门 题意:输出两字符串的最长公共子序列长度 分析:LCS(Longest Common Subsequence)裸题.状态转移方程:dp[i+1][j+1] = dp[i][j] + 1; ( ...

  8. hdu 1513 && 1159 poj Palindrome (dp, 滚动数组, LCS)

    题目 以前做过的一道题, 今天又加了一种方法 整理了一下..... 题意:给出一个字符串,问要将这个字符串变成回文串要添加最少几个字符. 方法一: 将该字符串与其反转求一次LCS,然后所求就是n减去 ...

  9. POJ 2250 Compromise(LCS)

    POJ 2250 Compromise(LCS)解题报告 题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=87125#proble ...

随机推荐

  1. 【ASP.Net MVC】AspNet Mvc一些总结

    AspNet Mvc一些总结 RestaurantReview.cs using System; using System.Collections.Generic; using System.Comp ...

  2. ZOJ3717 Balloon(2-SAT)

    一个很玄乎的问题,但听到2-SAT之后就豁然开朗了.题目的意思是这样的,给你n个点群,每个点群里面有两个点,你要在每个点群里面选一个点,以这些点做半径为r的圆,然后r会有一个最大值,问的就是怎么选这些 ...

  3. POJ 2141

    #include<iostream> #include<stdio.h> using namespace std; int main() { //freopen("1 ...

  4. UVA 562 Dividing coins

    题目描述:给出一些不同面值的硬币,每个硬币只有一个.将这些硬币分成两堆,并且两堆硬币的面值和尽可能接近. 分析:将所有能够取到的面值数标记出来,然后选择最接近sum/2的两个面值 状态表示:d[j]表 ...

  5. intelli IDEA node开发代码提示问题

    好几天没写代码了,今天新建一个项目,在引入rs这个文件系统模块时却没有关于这个模块的代码提示,着实令人恶心啊.还好最终解决了. 在没有代码提示的时候点击如下图标: 出现如下的界面,其中有个Edit u ...

  6. svn教程

    安装过程: 1.下载软件后,双击程序进行安装,点击“Next”: 2.在许可证协议页面,选择“I Accept the terms in the License Agreement”,点击“Next” ...

  7. linux系统中如何进入退出vim编辑器,方法及区别

    在linux家族中,vim编辑器是系统自带的文本编辑器,其功能强大自不必说了.偶有小白,刚接触linux,要修改某个文本文件,不可能像WINDOWS那样操作,更有甚者,进入VI编辑器后,无法退出以致强 ...

  8. SSH开发实践part2:双向1-N连接配置

    1 OK,上一篇已经介绍了项目开发的前期准备工作,具体内容可以参考:http://www.cnblogs.com/souvenir/p/3783686.html 按照开发步骤,我们现在已经可以开始进行 ...

  9. VBA高效删除不连续多行

    最近在搞VBA,在感叹Excel功能强大的同时,对于新接触的一门编程语言也很烦恼.很多基础的语法都要靠网上搜索.现总结一些学习到的心得. VBA高效删除不连续多行 在一个拥有几万条数据的Excel中, ...

  10. ios开发--GCD使用介绍:4-延迟执行操作

    在开发过程中,我们有时会希望把一些操作封装起来延迟一段时间后再执行.iOS开发中,有两种常用的方法可以实现延迟执行,一种是使用GCD,另外一种是使用NSRunLoop类中提供的方法. 1.使用GCD实 ...