CF1203D1/D2 Remove the Substring (easy/hard version)

Remove the Substring

传送门(hard版)

传送门(easy版)

题面翻译(此为hard版翻译,easy版仅将 1 ≤ ∣ s ∣ , ∣ t ∣ ≤ 2 × 1 0 5 1\leq |s|,|t|\leq 2\times 10^5 1s,t2×105改为 1 ≤ ∣ s ∣ , ∣ t ∣ ≤ 200 1\leq |s|,|t|\leq 200 1s,t200

题目描述:

请注意:本题简单版和困难版之间的唯一区别是字符串的长度限制。

给你一个字符串 s s s和一个字符串 t t t,两者都只包含小写字母。你可以通过从 s s s中删除一些字符(不必连续,可不删除)而不改变剩余字符的顺序(换句话说,删除一些字符后 t t t仍然是 s s s的子序列),保证最初 t t t s s s的子序列。
例如,字符串"test", “tst”, “tt”, “et"和”“都是字符串"test"的子序列,而"tset”, “se”, "contest"都不是字符串"test"的子序列。
您希望从s中删除一些最大可能长度的连续子序列,在删除后t仍将是s的子序列。
如果要删除子串 s [ l ; r ] s[l;r] s[l;r],则原字符串 s s s将变化为 s 1 s 2 . . . s l − 1 s r + 1 s r + 2 . . . s ∣ s ∣ − 1 s ∣ s ∣ s_1s_2...s_{l-1}s_{r+1}s_{r+2}...s_{|s|-1}s_{|s|} s1s2...sl1sr+1sr+2...ss1ss ∣ s ∣ |s| s为字符串 s s s的长度)。
找到可以删除的连续子字符串的最大可能长度,使得删除后 t t t仍将是 s s s的子序列。

输入格式:

第一行包含一个由小写拉丁字母组成的字符串 s s s。第二行包含一个由小写字母组成的字符串 t t t。( 1 ≤ ∣ s ∣ , ∣ t ∣ ≤ 2 × 1 0 5 1\leq |s|,|t|\leq 2\times 10^5 1s,t2×105),保证 t t t s s s的子序列。

输出格式:

输出一个整数,即可以删除的子字符串的最大可能长度,使得 t t t仍将是 s s s的子序列。

题目描述

The only difference between easy and hard versions is the length of the string.

You are given a string s s s and a string t t t , both consisting only of lowercase Latin letters. It is guaranteed that t t t can be obtained from s s s by removing some (possibly, zero) number of characters (not necessary contiguous) from s s s without changing order of remaining characters (in other words, it is guaranteed that t t t is a subsequence of s s s ).

For example, the strings “test”, “tst”, “tt”, “et” and “” are subsequences of the string “test”. But the strings “tset”, “se”, “contest” are not subsequences of the string “test”.

You want to remove some substring (contiguous subsequence) from s s s of maximum possible length such that after removing this substring t t t will remain a subsequence of s s s .

If you want to remove the substring $ s[l;r] $ then the string $ s $ will be transformed to s 1 s 2 … s l − 1 s r + 1 s r + 2 … s ∣ s ∣ − 1 s ∣ s ∣ s_1 s_2 \dots s_{l-1} s_{r+1} s_{r+2} \dots s_{|s|-1} s_{|s|} s1s2sl1sr+1sr+2ss1ss (where ∣ s ∣ |s| s is the length of s s s ).

Your task is to find the maximum possible length of the substring you can remove so that t t t is still a subsequence of s s s .

输入格式

The first line of the input contains one string s s s consisting of at least 1 1 1 and at most 2 ⋅ 1 0 5 2 \cdot 10^5 2105 lowercase Latin letters.

The first line of the input contains one string t t t consisting of at least 1 1 1 and at most 2 ⋅ 1 0 5 2 \cdot 10^5 2105 lowercase Latin letters.

It is guaranteed that t t t is a subsequence of s s s .

输出格式

Print one integer — the maximum possible length of the substring you can remove so that t t t is still a subsequence of s s s .

样例 #1

样例输入 #1

bbaba
bb

样例输出 #1

3

样例 #2

样例输入 #2

baaba
ab

样例输出 #2

2

样例 #3

样例输入 #3

abcde
abcde

样例输出 #3

0

样例 #4

样例输入 #4

asdfasdf
fasd

样例输出 #4

3

以上来自洛谷 以上来自洛谷 以上来自洛谷

解题思路

前言

由于本人较懒,故先打了hard版,再用hard版的代AC了easy版

正文

假设 s s s的长度为 n n n t t t的长度为 m m m。首先,暴力肯定是不行的了(因为要对标hard版),我们就得考虑找规律。通过推理可以发现,删除的字串大体可以分为三类:

  1. 删除 s s s最左边的子串;
  2. 删除 s s s最右边的子串;
  3. 删除 s s s中间的某个子串。
情况 1 1 1

由于要求可删除的子字符串的最大长度,所以要从 s s s的首位开始找,直至找到第一个与 t t t串相同的子字符串出现位置,记录下每一元素位置,并停止寻找。(说得不太清楚,直接看代码自行理解。)

len = 1;
for (int i = 1; i <= len1 && len <= len2; i++) {
	if (s[i] == t[len]) {
		a1[len++] = i;
	}
}
情况 2 2 2

与情况 1 1 1差不多,只是从 s s s末尾开始从后往前找,直至找到第一个与 t t t串相同的子字符串出现位置,记录下每一元素位置,并停止寻找。(看代码比较直观。)

len = len2;
for (int i = len1; i >= 1 && len >= 1; i--) {
	if (s[i] == t[len]) {
		a2[len--] = i;
	}
}

在完成之后, a n s = m a x ( a 2 1 − 1 , l e n 1 − a 1 l e n 2 ) ans = max(a2_1 - 1, len1 - a1_{len2}) ans=max(a211,len1a1len2)

情况 3 3 3

s s s中找到最前与最后的与 t t t相同的子字符串后,要删中间的字串就相当于吧最前与最后的子字符串拼接起来。

for (int i = 1; i < len2; i++) {
	ans = max(ans, a2[i + 1] - a1[i] - 1);
}

AC Code

// C++ includes used for precompiling -*- C++ -*-

// Copyright (C) 2003-2013 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR a2 PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <Licenses - GNU Project - Free Software Foundation>.

/** @file stdc++.h
 *  This is an implementation file for a precompiled header.
 */

// 17.4.1.2 Headers

// C
#ifndef _GLIBCXX_NO_ASSERT
	#include <cassert>
#endif
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>

#if __cplusplus >= 201103L
	#include <ccomplex>
	#include <cfenv>
	#include <cinttypes>
	#include <cstdalign>
	#include <cstdbool>
	#include <cstdint>
	#include <ctgmath>
	#include <cwchar>
	#include <cwctype>
#endif

// C++
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>

#if __cplusplus >= 201103L
	#include <array>
	#include <atomic>
	#include <chrono>
	#include <condition_variable>
	#include <forward_list>
	#include <future>
	#include <initializer_list>
	#include <mutex>
	#include <random>
	#include <ratio>
	#include <regex>
	#include <scoped_allocator>
	#include <system_error>
	#include <thread>
	#include <tuple>
	#include <typeindex>
	#include <type_traits>
	#include <unordered_map>
	#include <unordered_set>
#endif
using namespace std;
#define int long long
const int Maxn = 2e5 + 5;
char s[Maxn], t[Maxn];
int len1, len2, len, a1[Maxn], a2[Maxn];
int ans;
inline void work() {
	cin >> s + 1 >> t + 1;
	len1 = strlen(s + 1), len2 = strlen(t + 1);
	len = 1;
	for (int i = 1; i <= len1 && len <= len2; i++) {
		if (s[i] == t[len]) {
			a1[len++] = i;
		}
	}
	len = len2;
	for (int i = len1; i >= 1 && len >= 1; i--) {
		if (s[i] == t[len]) {
			a2[len--] = i;
		}
	}
	ans = max(a2[1] - 1, len1 - a1[len2]);
	for (int i = 1; i < len2; i++) {
		ans = max(ans, a2[i + 1] - a1[i] - 1);
	}
	cout << ans << endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	work();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值