Codeforces - 1203D2 - Remove the Substring (hard version) - 双指针

https://codeforces.com/contest/1203/problem/D2

上次学了双指针求两个字符串之间的是否t是s的子序列。但其实这个双指针可以求出的是s的前i个位置中匹配t的最长的前缀。反过来求一次可以得到最长的后缀。

然后怎么找要删除的位置呢?暴力n^2肯定可以,然后线性写挂到自闭。

枚举位置[i,j),注意j可以取相等,所以预处理前后缀的时候把n位置的后缀也算好。

去除子串[i,j),那么剩下的就是[0,i-1]和[j,n-1]两个子串,他们匹配的长度加起来超过tl就是合法。

#include<bits/stdc++.h>
using namespace std;

int dpprefix[200005];
int dpsuffix[200005];

char s[200005], t[200005];
int sl, tl;

void prefix() {
    int i = 0, j = 0;
    while(i < sl || j < tl) {
        if(i < sl && j < tl) {
            if(s[i] == t[j]) {
                dpprefix[i] = j + 1;
                ++i, ++j;
            } else {
                dpprefix[i] = j;
                ++i;
            }
        } else if(j == tl) {
            dpprefix[i] = tl;
            ++i;
        } else if(i == sl) {
            dpprefix[i] = j;
            break;
        }
    }
}

void suffix() {
    int i = sl - 1, j = tl - 1;
    while(i >= 0 || j >= 0) {
        if(i >= 0 && j >= 0) {
            if(s[i] == t[j]) {
                dpsuffix[i] = tl - j;
                --i, --j;
            } else {
                dpsuffix[i] = tl - (j + 1);
                --i;
            }
        }  else if(j < 0) {
            dpsuffix[i] = tl;
            --i;
        } else if(i < 0) {
            dpprefix[i] = tl - j;
            break;
        }
    }
}

int main() {
#ifdef Yinku
    freopen("Yinku.in", "r", stdin);
#endif // Yinku
    while(~scanf("%s%s", s, t)) {
        memset(dpprefix, 0, sizeof(dpprefix));
        memset(dpsuffix, 0, sizeof(dpsuffix));
        sl = strlen(s), tl = strlen(t);
        prefix();
        suffix();
        int i = 0, j = 1;
        int ans = 0;
        while(i < sl || j <= sl) {
            if(i == 0) {
                while(j <= sl && dpsuffix[j] >= tl) {
                    ans = max(ans, j - i);
                    ++j;
                }
            } else {
                while(j <= sl && dpprefix[i - 1] + dpsuffix[j ] >= tl) {
                    ans = max(ans, j - i);
                    ++j;
                }
            }
            ++i;
        }
        printf("%d\n", ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Yinku/p/11355706.html

时间: 2024-10-31 04:29:40

Codeforces - 1203D2 - Remove the Substring (hard version) - 双指针的相关文章

Codeforces 1203D2 Remove the Substring (hard version)

题目链接:https://www.luogu.org/problem/CF1203D2 题意:给你两个字符串s,t(长度为2e5),保证t是s的子序列,求问最大能在s中删子串的长度,且保证删后t还是s的子序列 分析:先求pre和last两个数组,分别保存最左边的满足t的子序列后最右边的满足t的子序列. 之后依次比较即可 #include<bits/stdc++.h> using namespace std; typedef long long ll; const int inf=0x3f3f3

题解 CF1203D2 【Remove the Substring (hard version)】

题目链接 Solution CF1203D 题目大意:给定两个字符串\(s\),\(t\), \(t\)是\(s\)的子序列,问最长可以在\(s\)里面删掉多长的连续子序列使得\(t\)仍为\(s\)的子序列 贪心 分析: 假如我们\(t\)的一个前缀要匹配\(s\)的话,显然尽可能往前匹配,这样可以使得答案尽量大,后缀同理 我们用\(suf[i]\)表示\(t[1\dots i]\)可以匹配\(s\)前缀的最前的位置,\(suf[i]\)表示\(t[i \dots |t|]\)可以匹配\(s\

Codeforces Round #575 (Div. 3) D1. RGB Substring (easy version)

Codeforces Round #575 (Div. 3) D1 - RGB Substring (easy version) The only difference between easy and hard versions is the size of the input. You are given a string s consisting of n characters, each character is 'R', 'G' or 'B'. You are also given a

【Codeforces Round #575 (Div. 3) 】 RGB Substring (hard version) ( FFT)

D2. RGB Substring (hard version) time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output The only difference between easy and hard versions is the size of the input. You are given a string ss cons

D2. RGB Substring (hard version)||D1. RGB Substring (easy version)

D2. RGB Substring (hard version)    原题传送门 time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output The only difference between easy and hard versions is the size of the input. You are given a strin

Codeforces 1335E2 - Three Blocks Palindrome (hard version)

题面 题意/解题思路 直接延用 Easy 版本的想法即可 详解见上一篇博客Codeforces 1335E1 - Three Blocks Palindrome (easy version) 完整程序 (93ms/2000ms) #include<bits/stdc++.h> using namespace std; int ar[200050]; vector<int> v[210]; void solve() { int n,ans=0; cin>>n; for(i

Codeforces Round #575 (Div. 3) D2. RGB Substring (hard version)

传送门 题意: 给你一个长为n的仅由'R','G','B'构成的字符串s,你需要在其中找出来一个子串.使得这个子串在“RGBRGBRGBRGB........(以RGB为循环节,我们称这个串为str)”里面也是一个子串,这个子串的长度是k 可是有可能s字符串中找不到,那么这个时候就可以改变s字符串中某些位置的字母来完成任务.问最少需要改变多少个字母 题解: 主要看暴力的姿势对不对.在上一道的D1上面,我是对s字符串的每一个位置进行‘R’,‘G’,‘B’的枚举,因为如果这个子串也是str的子串的话

Codeforces 1108E2 Array and Segments (Hard version) 差分, 暴力

Codeforces 1108E2 E2. Array and Segments (Hard version) Description: The only difference between easy and hard versions is a number of elements in the array. You are given an array \(a\) consisting of \(n\) integers. The value of the \(i\)-th element

Codeforces 900C. Remove Extra One(暴力)

You are given a permutation p of length n. Remove one element from permutation to make the number of records the maximum possible. We remind that in a sequence of numbers a1, a2, ..., ak the element ai is a record if for every integer j (1 ≤ j < i) t