• [CF762C] Two Strings(预处理,二分答案)


    题目链接:http://codeforces.com/contest/762/problem/C

    题意:两个字符串a、b。希望在a中删掉连续的字符串,使得b是a的子序列。

    希望删掉的是连续的字符串,那么可以预处理两个数组pre和suf。

    pre(i)表示b[0,i]为a的子序列,a的最短长度。

    suf(i)表示b[i,na)为a的子序列,a倒着数的最短长度。

    会发现这两个数列是单调的,二分答案len,表示中间删掉的字符串长度为len。O(n)枚举a删除的起始点,判断即可。

    注意判断时枚举到起点为0,即无前缀的时候,要判断这时后缀长度是否满足条件。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 const int maxn = 100100;
     5 char a[maxn], b[maxn];
     6 int na, nb;
     7 int pre[maxn], suf[maxn];
     8 bool exflag;
     9 string ret;
    10 
    11 bool ok(int len) {
    12     for(int i = 0; i <= nb-len; i++) {
    13         if((i == 0 && suf[len] >= 0) || pre[i-1] < suf[i+len]) {
    14             ret = "";
    15             exflag = 1;
    16             for(int j = 0; j < i; j++) ret += b[j];
    17             for(int j = i+len; b[j]; j++) ret += b[j];
    18             return 1;
    19         }
    20     }
    21     return 0;
    22 }
    23 
    24 int main() {
    25     // freopen("in", "r", stdin);
    26     memset(a, 0, sizeof(a));
    27     memset(a, 0, sizeof(b));
    28     while(~scanf("%s%s",a,b)) {
    29         na = strlen(a); nb = strlen(b);
    30         memset(pre, 0, sizeof(pre));
    31         memset(suf, 0, sizeof(suf));
    32         int p = 0;
    33         for(int i = 0; i < nb; i++, p++) {
    34             while(p < na && a[p] != b[i]) p++;
    35             pre[i] = p;
    36         }
    37         p = na - 1;
    38         for(int i = nb-1; i >= 0; i--, p--) {
    39             while(p >= 0 && a[p] != b[i]) p--;
    40             suf[i] = p;
    41         }
    42         suf[nb] = na;
    43         // for(int i = 1; i <= nb; i++) printf("%d ", pre[i]); printf("
    ");
    44         // for(int i = 1; i <= nb; i++) printf("%d ", suf[i]); printf("
    ");
    45         exflag = 0; ret = "";
    46         int lo = 0, hi = nb - 1;
    47         while(lo <= hi) {
    48             int mid = (lo + hi) >> 1;
    49             if(ok(mid)) hi = mid - 1;
    50             else lo = mid + 1;
    51         }
    52         if(!exflag) puts("-");
    53         else cout << ret << endl;
    54         memset(a, 0, sizeof(a));
    55         memset(a, 0, sizeof(b));
    56     }
    57     return 0;
    58 }
  • 相关阅读:
    Git远程仓库的使用(github为例)
    SQL查看数据库中每张表的数据量和总数据量
    HTML简单的注册页面搭建
    java新建日期获取工具
    ArrayList的使用方法技巧(转载)
    UI初级 TextField
    UI初级 Label
    UI入门 纯代码 第一节 UIWindow, UIView
    C 入门 第十一节
    secoclient安装mac版提示系统配置文件写入失败的解决方案
  • 原文地址:https://www.cnblogs.com/kirai/p/6874482.html
Copyright © 2020-2023  润新知