zoukankan      html  css  js  c++  java
  • [ZJOI 2013]丽洁体

    Description

    题库链接

    给出四个字符串 (T,A,B,C) ,问你至少在 (T) 串中删去几个单词能使得 (T) 串变为 (A?B?C) 的形式,其中 (?) 表示任意多的单词,可以为空。

    (1leq |T|,|A|,|B|,|C|leq 50000)

    Solution

    首先注意到不同的字符串最多有 (O(26^5)) 个。我们可以先把字符串 (hash) ,方便处理。

    其次,容易发现的是对于要满足 (A,C) 串的要求,直接贪心就好了,分别从串前和尾扫一遍。

    我们考虑如何选 (B) 。我们先把 (T) 串中 (A,C) 相关的部分去掉。

    一个显然的 (DP) 是记 (f_{i,j}) 为处理过的 (T) 串前 (i) 位选中了 (B) 串前 (j) 位要删去的最少单词数。但这样转移是 (O(|T||B|)) 的,能拿 (70pts)

    转换思路。

    (f_i) 表示第 (i) 位的字符最晚在 (T) 串的哪个位置出现; (g_i) 表示匹配前 (i) 位最少删除的字符。

    注意到相同的字符最多只有 (500) ,我们可以暴力枚举所有的在 (B) 串中与 (T_i) 相同的位置。这样复杂度为 (O(500|T|))

    当然了,如果用相同的思想,枚举所有的在 (B) 串中与 (T_i) 相同的位置。用线段树优化 (70pts) 是可以做到 (O(500|T|log_2 |B|))

    Code

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 250000, M = 12356630, inf = 2e9;
    
    char T[N+5], A[N+5], B[N+5], C[N+5];
    int t[N+5], a[N+5], b[N+5], c[N+5], tt, ta, tb, tc, L, R, ans;
    int f[N+5], g[N+5];
    vector<int>s[M+5];
    void get(char *ch, int *a, int &tot) {
        int len = 0; char c;
        while ((c = getchar()) != '
    ') ch[++len] = c;
        for (int i = 1, j; i <= len; i = j+1) {
        int sum = 0; j = i;
        while (ch[j] >= 'a' && ch[j] <= 'z') sum = sum*26+ch[j]-'a'+1, ++j;
        a[++tot] = sum;
        }
    }
    void work() {
        get(T, t, tt);
        get(A, a, ta);
        get(B, b, tb);
        get(C, c, tc);
        for (int i = 1, loc = 1; i <= tt; i++) {
        if (t[i] == a[loc]) ++loc;
        else ans++;
        if (loc == ta+1) {L = i+1; break; }
        }
        for (int i = tt, loc = tc; i >= 1; i--) {
        if (t[i] == c[loc]) --loc;
        else ans++;
        if (loc == 0) {R = i-1; break; }
        }
        int sum = inf;
        memset(g, 127/3, sizeof(g));
        for (int i = 1; i <= tb; i++) s[b[i]].push_back(i);
        for (int i = L; i <= R; i++)
        for (int j = s[t[i]].size()-1; j >= 0; j--) {
            int x = s[t[i]][j];
            if (x == 1) f[x] = i, g[x] = 0;
            else if (f[x-1]) f[x] = i, g[x] = g[x-1]+i-f[x-1]-1;
            sum = min(sum, g[tb]);
        }
        printf("%d
    ", sum+ans);
    }
    int main() {work(); return 0; }
  • 相关阅读:
    图片上传-下载-删除等图片管理的若干经验总结3-单一业务场景的完整解决方案
    图片上传-下载-删除等图片管理的若干经验总结2
    HDU 1195 Open the Lock
    HDU 1690 Bus System
    HDU 2647 Reward
    HDU 2680 Choose the best route
    HDU 1596 find the safest road
    POJ 1904 King's Quest
    CDOJ 889 Battle for Silver
    CDOJ 888 Absurdistan Roads
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/8672734.html
Copyright © 2011-2022 走看看