zoukankan      html  css  js  c++  java
  • bzoj 2423 最长公共子序列

    题意:

    中文题意,略。。。

    思路:

    第一问,求最长公子序列,模板题。。。

    第二问,求最长公共子序列的个数,这个就比较有意思了。

    设len[i][j]表示表示第一个串到i位置,第二个串到j位置时的长度。

    设lcs[i][j]表示第一个串到i位置,第二个串到j位置时,lcs的个数。

    当a[i] == b[j]:

    那么最长公共子序列肯定是可以从i-1,j-1的位置继承来的,所以lcs[i][j] += lcs[i-1][j-1];

    当len[i][j-1] = len[i][j],说明lcs也可以从i,j-1的位置继承来,那么lcs[i][j] += lcs[i][j-1];

    当len[i-1][j] = len[i][j],同理。

    当a[i] != b[j]时:

    要么从i – 1,j的位置继承而来,要么从i,j-1的位置继承而来。

    但是当len[i][j-1] = len[i-1][j]时,说明两个lcs均是从i-1,j-1的位置继承而来,那么以i-1,j-1结尾的lcs的个数就被加了两次,所以要减去一次。

    然后这题限制空间,所以得用滚动数组优化。

    代码:

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 const int N = 5005;
     7 const int mod = 1e8;
     8 
     9 char x[N],y[N];
    10 
    11 int a[2][N],b[2][N];
    12 
    13 int main()
    14 {
    15     while (scanf("%s%s",x+1,y+1) != EOF)
    16     {
    17         int n = strlen(x+1) - 1;
    18         int m = strlen(y+1) - 1;
    19         
    20         for (int i = 0;i <= m;i++) b[0][i] = 1;
    21         b[1][0] = 1;
    22         
    23         for (int i = 1;i <= n;i++)
    24         {
    25             for (int j = 1;j <= m;j++)
    26             {
    27                 int c = i % 2,p = 1 - c;
    28                 
    29                 if (x[i] == y[j])
    30                 {
    31                     a[c][j] = a[p][j-1] + 1;
    32                     
    33                     int tmp = b[p][j-1] % mod;
    34                     
    35                     if (a[c][j] == a[c][j-1]) tmp = (tmp + b[c][j-1]) % mod;
    36                     if (a[c][j] == a[p][j]) tmp = (tmp + b[p][j]) % mod;
    37                     
    38                     b[c][j] = tmp;
    39                 }
    40                 else
    41                 {
    42                     a[c][j] = max(a[p][j],a[c][j-1]);
    43                     
    44                     int tmp = 0;
    45                     
    46                     if (a[c][j] == a[p][j]) tmp = (tmp + b[p][j]) % mod;
    47                     if (a[c][j] == a[c][j-1]) tmp = (tmp + b[c][j-1]) % mod;
    48                     if (a[c][j] == a[p][j-1]) tmp = (tmp - b[p][j-1]) % mod;
    49                     
    50                     b[c][j] = tmp;
    51                 }
    52             }
    53         }
    54         
    55         printf("%d
    %d
    ",a[n%2][m],(b[n%2][m]+mod) % mod);
    56     }
    57     
    58     return 0;
    59 }
  • 相关阅读:
    RMQ 算法入门
    hdu1535——Invitation Cards
    LeetCode 206. Reverse Linked List(迭代和递归两种实现)
    CSDN开源夏令营 基于Compiz的switcher插件设计与实现之前期准备 git的简单使用
    xml初学简单介绍
    do{}while(0)与CC_BREAK_IF的绝妙搭配
    《Python基础教程》第20章学习笔记
    oracle启动过程2
    Javascript 笔记与总结(1-6)Javascript 面向对象
    [Swift]LeetCode44. 通配符匹配 | Wildcard Matching
  • 原文地址:https://www.cnblogs.com/kickit/p/8808753.html
Copyright © 2011-2022 走看看