zoukankan      html  css  js  c++  java
  • poj 1934(LCS)

    转自: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。

     1 // File Name: 1934.cpp
     2 // Author: Missa_Chen
     3 // Created Time: 2013年07月07日 星期日 20时21分33秒
     4 
     5 #include <iostream>
     6 #include <string>
     7 #include <algorithm>
     8 #include <cstdio>
     9 #include <cstring>
    10 #include <cmath>
    11 #include <queue>
    12 #include <map>
    13 #include <stack>
    14 #include <set>
    15 #include <cstdlib>
    16 #include <vector>
    17 #include <time.h>
    18 
    19 using namespace std;
    20 const int maxn = 100;
    21 int dp[maxn][maxn];
    22 int last1[maxn][27], last2[maxn][27];
    23 set <string> ans;
    24 char tmp[maxn];
    25 void dfs(int s1, int s2, int len)
    26 {
    27     if (len <= 0)
    28     {
    29         ans.insert(tmp);
    30         return ;
    31     }
    32     if (s1 > 0 && s2 > 0)
    33     {
    34         for (int i = 0; i < 26; ++i)
    35         {
    36             int t1 = last1[s1][i];
    37             int t2 = last2[s2][i];
    38             if (dp[t1][t2] == len)
    39             {
    40                 tmp[len - 1] = 'a' + i;
    41                 dfs(t1 - 1, t2 - 1, len - 1);
    42             }
    43         }
    44     }
    45     return ;
    46 }
    47 void LCS(string s1, string s2)
    48 {
    49     memset(dp, 0, sizeof(dp));
    50     for (int i = 1; i <= s1.size(); ++i)
    51     {
    52         for (int j = 1; j <= s2.size(); ++j)
    53         {
    54             if (s1[i - 1] == s2[j - 1])
    55                 dp[i][j] = dp[i - 1][j - 1] + 1;
    56             else dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
    57         }
    58     }
    59 }
    60 void solve(string s1, string s2)
    61 {
    62     memset(last1, 0, sizeof(last1));
    63     memset(last2, 0, sizeof(last2));
    64     for (int i = 1; i <= s1.size(); ++i)
    65     {
    66         for (int j = 0; j < 26; ++j)
    67             last1[i][j] = last1[i - 1][j];
    68         last1[i][s1[i - 1] - 'a'] = i;
    69     }
    70     for (int i = 1; i <= s2.size(); ++i)
    71     {
    72         for (int j = 0; j < 26; ++j)
    73             last2[i][j] = last2[i - 1][j];
    74         last2[i][s2[i - 1] - 'a'] = i;
    75     }
    76     tmp[dp[s1.size()][s2.size()]] = '';
    77     dfs(s1.size(), s2.size(), dp[s1.size()][s2.size()]);
    78     for (set <string> :: iterator it = ans.begin(); it != ans.end(); ++it)
    79         cout <<*it<<endl;
    80 }
    81 int main()
    82 {
    83     string s1, s2;
    84     while (cin >> s1 >> s2)
    85     {
    86         LCS(s1, s2);
    87         solve(s1, s2);
    88     }
    89     return 0;
    90 }
  • 相关阅读:
    有点忙啊
    什么是协程
    HDU 1110 Equipment Box (判断一个大矩形里面能不能放小矩形)
    HDU 1155 Bungee Jumping(物理题,动能公式,弹性势能公式,重力势能公式)
    HDU 1210 Eddy's 洗牌问题(找规律,数学)
    HDU1214 圆桌会议(找规律,数学)
    HDU1215 七夕节(模拟 数学)
    HDU 1216 Assistance Required(暴力打表)
    HDU 1220 Cube(数学,找规律)
    HDU 1221 Rectangle and Circle(判断圆和矩形是不是相交)
  • 原文地址:https://www.cnblogs.com/Missa/p/3176866.html
Copyright © 2011-2022 走看看