zoukankan      html  css  js  c++  java
  • Codeforces Round #579 (Div. 3)

    D1  题目链接

     题目大意是有一个原串s 和 模式串 t ,保证 t 是 s 的子序列 ,二者长度均小于200,现在可以将原串s中删去一个子串再将剩余部分拼起来,使得修改后的s仍有一个子序列与t相等,现在问满足条件的删去子串的最长长度。

    直接暴力尝试删去每个子串,再检查剩余部分是否有子序列与t相等。

     1     #include <bits/stdc++.h>
     2     using namespace std;
     3      
     4     const int maxn = 200 + 10;
     5      
     6     bool checksub(string s,string t,int lent){
     7         int lens = s.length();
     8         int ind = 0;
     9         for (int i = 0; i < lens; ++i) {
    10             if(s[i] == t[ind]) ind++;
    11             if(ind == lent){
    12                 return true;
    13             }
    14         }
    15         return false;
    16     }
    17      
    18     int main(){
    19         ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
    20         string strS,strT;
    21         cin >> strS >> strT;
    22         int lenS = strS.length() , lenT = strT.length();
    23         int ans = 0;
    24         for (int i = 0; i < lenS; ++i) {
    25             for (int j = i; j < lenS; ++j) {
    26                 string tmp = strS;
    27                 tmp.erase(i,j-i+1);
    28                 if(checksub(tmp,strT,lenT)){
    29                     ans = max(ans, j- i + 1);
    30                 }
    31             }
    32         }
    33         cout << ans ;
    34         return 0;
    35     }
    View Code

    复杂度差不多是O(n^3)。

    D2  题目链接

    题目与D1相同,只是长度限制由200变为2e5,不能暴力了。

    暴力做法里有很多删去子串是不满足剩余部分仍含有子序列t的,其实就是有很多不必要的删去。试想一个满足条件的删去,删后的左边子串一定是包含t的左侧某部分,删后的右边子串则是包含t的右侧某部分,然后我们尽量拉长这个删去子串直到遇到t的匹配字符位置。这样理解问题就变成找出t中每个字符在s中最靠左与最靠右的匹配。

    其实我们在之前检查t是否为s的子序列时,是从左至右贪心处理的,这样匹配的子序列一定是原串中最靠左的。试想如果提前从右至左贪心,则可预存每个t中字符在原串中最靠右的匹配位置。相邻字符,一左一右,这样我们就可以保证删去子串在满足条件的情况下最长。注意头尾特判。

     1     #include <bits/stdc++.h>
     2     using namespace std;
     3      
     4     const int maxn = 2e5 + 10;
     5     char strS[maxn] , strT[maxn];
     6     int Rmost[maxn];
     7     int main(){
     8         scanf("%s%s",strS,strT);
     9         int lenS = strlen(strS) , lenT = strlen(strT);
    10         int ind = lenT - 1;
    11         for (int i = lenS - 1; i >= 0; i--) {
    12             if(strS[i] == strT[ind]){
    13                 Rmost[ind] = i;
    14                 ind --;
    15             }
    16             if(ind == -1) break;
    17         }
    18         ind = 0;
    19         int ans = Rmost[0]; // rm the Leftmost substring
    20     //    for(int i = 0;i < lenT;++i) printf("Rmost %d : %d
    ",i,Rmost[i]);
    21         for (int i = 0; i < lenS; ++i) {
    22             if(strS[i] == strT[ind]){
    23                 if(ind == lenT - 1) ans = max(ans , lenS - 1 - i);// rm the Rightmost substring;
    24                 else ans = max(ans, Rmost[ind+1] - i - 1);
    25                 ind ++ ;
    26             }
    27             if(ind == lenT) break;
    28         }
    29         printf("%d
    ",ans);
    30         return 0;
    31     }
    View Code

    复杂度为O(n)。

  • 相关阅读:
    简单的方法爬取b站dnf视频封面步骤解释
    ROS讲座 关于ROS2和Gazebo C++ in Open Source Robotics
    深圳3分钟完成港澳签注 24小时自助办证服务攻略
    如何建立数据平台?看上市公司的选择!
    从开发转型到技术总监的迷茫
    计算机控制技术课程解释与问题答疑
    深度剖析 | 基于大数据架构的BI应用
    Android系统开机启动流程及init进程浅析
    经验分享 | 如何搭建企业管理驾驶舱
    android 修改framework下资源文件后如何编译
  • 原文地址:https://www.cnblogs.com/Kiritsugu/p/11531003.html
Copyright © 2011-2022 走看看