• 2019.10.25字符串——zr


    题意:

    给你两个字符串,由01组成;求他们两个的最短公共非子序列,要求字典序最小;

    非公共子序列:都不是这两个字符串的子序列;

    本人只会暴力啊,二进制枚举稳拿15分;

    然而这道题其实是一个最短路题;

    题解:

    贪心考虑从前往后s1……si,维护一个j表示当前字符串已经匹配到t1……tj,

    贪心考虑tj'=si+1的j'匹配;

    要求字典序最小,实际上我们求得就是一个最短路;

    从中止状态反向遍历,就可以记录哪些点在起点到终点的最短路上。DP的状态就是最短路;

    再从开始点开始,哪个状态在最短路上,就输出;

    时间复杂度(n2);

    我觉得吧,其实就是在这两个字符串上找到最短的公共子串(感性理解,实际上并不是这个意思),我们要匹配到n+1,m+1,一个串结束了,并不代表状态的结束;

    因为当前状态+0/1可能还是较长串的子序列;

    当我们匹配到n+1,m+1的时候就是最短非公共子序列;

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int maxn=4010;
     6 int n,m;
     7 char s[maxn],t[maxn];
     8 
     9 int nxt_s[maxn][2],nxt_t[maxn][2];
    10 
    11 int dp[maxn][maxn];
    12 
    13 int on_road[maxn][maxn];
    14 
    15 int main()
    16 {
    17     scanf("%d%d",&n,&m);
    18     scanf("%s%s",s+1,t+1);
    19     nxt_s[n+1][0]=nxt_s[n+1][1]=n+1;
    20     for(int i=n;i>=1;i--)
    21     {
    22         int c=s[i]-'0';
    23         nxt_s[i][c]=i;
    24         nxt_s[i][c^1]=nxt_s[i+1][c^1];
    25     }
    26     nxt_t[m+1][0]=nxt_t[m+1][1]=m+1;
    27     for(int i=m;i>=1;i--)
    28     {
    29         int c=t[i]-'0';
    30         nxt_t[i][c]=i;
    31         nxt_t[i][c^1]=nxt_t[i+1][c^1];
    32     }
    33     
    34     memset(dp,0x3f,sizeof(dp));
    35     dp[0][0]=0;
    36     for(int i=0;i<=n+1;i++)
    37     {
    38         for(int j=0;j<=m+1;j++)
    39         {
    40             for(int c=0;c<2;c++)
    41             {
    42                 int x=i<=n?nxt_s[i+1][c]:i;
    43                 int y=j<=m?nxt_t[j+1][c]:j;
    44                 if(dp[x][y]>dp[i][j]+1)
    45                 {
    46                     dp[x][y]=dp[i][j]+1;
    47                 }
    48             }
    49         }
    50     }
    51     
    52     on_road[n+1][m+1]=1;
    53     for(int i=n+1;i>=0;i--)
    54     {
    55         for(int j=m+1;j>=0;j--)
    56         {
    57             for(int c=0;c<2;c++)
    58             {
    59                 int x=i<=n?nxt_s[i+1][c]:i;
    60                 int y=j<=m?nxt_t[j+1][c]:j;
    61                 if(dp[x][y]==dp[i][j]+1&&on_road[x][y])
    62                 {
    63                     on_road[i][j]=1;
    64                 }
    65             }
    66         }
    67     }
    68     
    69     int i=0,j=0;
    70     
    71     while(i<=n||j<=m)
    72     {
    73         for(int c=0;c<2;c++)
    74         {
    75             int x=(i<=n?nxt_s[i+1][c]:i);
    76             int y=(j<=m?nxt_t[j+1][c]:j);
    77             if(dp[x][y]==dp[i][j]+1&&on_road[x][y])
    78             {
    79                 putchar(c+'0');
    80                 i=x;j=y;
    81                 break;
    82             }
    83         }
    84     }
    85     
    86     return 0;
    87 }
    View Code
  • 相关阅读:
    linux下一个网卡配置多个ip(转)
    实验室生活:第一个月
    关闭或开启Linux上的iptables防火墙,SSH端口(转)
    TcpTrace追踪远程服务器的soap信息
    我的mysql学习笔记(1)mysql的安装
    大型网站架构演变和知识体系[转载]
    ms sql一些有用的语句
    我的mysql学习笔记(2)mysql基本的命令
    SQL Server 2008 R2数据库镜像部署[转]
    C++ 自定义动态数组模板
  • 原文地址:https://www.cnblogs.com/WHFF521/p/11739400.html
Copyright © 2020-2023  润新知