Codeforces Round #579 (Div. 3)

时间:2019-09-16
本文章向大家介绍Codeforces Round #579 (Div. 3),主要包括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\n",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\n",ans);
30         return 0;
31     }
View Code

复杂度为O(n)。

原文地址:https://www.cnblogs.com/Kiritsugu/p/11531003.html