zoukankan      html  css  js  c++  java
  • E

    题目:传送门

    题目:给你三个字符串a, b, c,他们都是字符串 s 的连续子串,字符 '?' 可以是任何字符,问字符串 s 的长度最小是多少。

    1 <= len(a),len(b),len(c) <= 2000

    思路:

    很容易的可以想到一个贪心,就是,按照 a -> b -> c 这样的顺序去构造 s(共有六种方式,这里只列举一种),每次都尽可能的将 b 左移,将 c 左移, 这里有一个反例。

    例如: a = ??c?, b = ac?a,c = ?b?a

    按照上面的贪心策略,就是:

    1、??c?(字符串a)

    2、acca(字符串a和b合并,得到最优的ab)

    3、accab?a(最优的ab和字符串c合并)

    但是,最优的构造方式是:

    1、??c?(字符串 a )

    2、?ac?a(字符串 a 和 b 合并,得到 ab,b[0] 和 a[1] 对应)

    3、?acbaa(字符串 ab 和字符串 c 合并,c[0] 和 ab[2] 对应)

    所以这种贪心策略是错误的。

    我们可以预处理字符串 a 和字符串 b 的匹配情况

    ab[i]:表示,b 相对于 a 移动了 i 之后,是不是能匹配,例如我们假设 a = 12345, b = 2345,

    那么 ab[1] 就是 a[1] 和 b[0] 对应,然后后面的也一 一对应是不是能匹配

    12345

      2345

    b[0] 和 a[1] 对应,b[1] 和 a[2] 对应,b[2] 和 a[3] 对应,b[3] 和 a[4] 对应,这样的对应,i - j 都是等于 1 的( i 是字符串 a 对应的下标,j 是字符串 b 对应的下标),所以只要有一个不等,就将 ab[1] 置为 1,表示不匹配。

    按照同样的思路,预处理出 ac 和 bc

    然后,就枚举 ab 的偏移量和 ac 的偏移量,判断是否能更新答案就行了。

    复杂度 o(n^2)

    #include <bits/stdc++.h>
    #define LL long long
    #define mem(i, j) memset(i, j, sizeof(i))
    #define rep(i, j, k) for(int i = j; i <= k; i++)
    #define dep(i, j, k) for(int i = k; i >= j; i--)
    #define pb push_back
    #define make make_pair
    #define INF INT_MAX
    #define inf LLONG_MAX
    #define PI acos(-1)
    using namespace std;
    
    const int N = 2e4 + 5, up = 4000;
    
    char a[N], b[N], c[N];
    bool ab[N], ac[N], bc[N];
    
    int main() {
        scanf("%s", a);
        scanf("%s", b);
        scanf("%s", c);
        int lena = strlen(a);
        int lenb = strlen(b);
        int lenc = strlen(c);
    
        rep(i, 0, lena - 1) rep(j, 0, lenb - 1) /// 预处理 ab
            if(!(a[i] == b[j] || a[i] == '?' || b[j] == '?')) ab[i - j + up] = 1;
        rep(i, 0, lena - 1) rep(j, 0, lenc - 1) /// 预处理 ac
            if(!(a[i] == c[j] || a[i] == '?' || c[j] == '?')) ac[i - j + up] = 1;
        rep(i, 0, lenb - 1) rep(j, 0, lenc - 1) /// 预处理 bc
            if(!(b[i] == c[j] || b[i] == '?' || c[j] == '?')) bc[i - j + up] = 1;
    
        int ans = INF;
    
        rep(i, -4000, 4000) rep(j, -4000, 4000)
            if(!ab[i + up] && !ac[j + up] && !bc[j - i + up]) { ///b相对于a偏移了i,c相对于i偏移了j,c相对于b偏移了j - i
                int L = min({0, i, j});
                int R = max({lena, lenb + i, lenc + j});
                ans = min(ans, R - L);
            }
    
        printf("%d
    ", ans);
    
        return 0;
    }
    一步一步,永不停息
  • 相关阅读:
    kettle初探
    ECLIPSE 不能连接MYSQL 8 的现象
    easyreport 安装手记
    eclipse 下安装 lombok.jar
    mysql 8 安装及更改密码
    转:Python的这几个技巧,简直屌爆了
    转:通用缩写表
    检查webpack版本
    vue-cli脚手架项目按需引入elementUI
    webstorm “Unterminated statement”
  • 原文地址:https://www.cnblogs.com/Willems/p/12517857.html
Copyright © 2011-2022 走看看