D2. Remove the Substring

D2. Remove the Substring (hard version)

The only difference between easy and hard versions is the length of the string.
You are given a string s and a string t, both consisting only of lowercase Latin letters. It is guaranteed that t can be obtained from s by removing some (possibly, zero) number of characters (not necessary contiguous) from s without changing order of remaining characters (in other words, it is guaranteed that t is a subsequence of 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 of maximum possible length such that after removing this substring t will remain a subsequence of s.

If you want to remove the substring s[l;r] then the string s will be transformed to s1s2…sl−1sr+1sr+2…s|s|−1s|s| (where |s| is the length of s).

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

Input
The first line of the input contains one string s consisting of at least 1 and at most 2⋅105 lowercase Latin letters.

The second line of the input contains one string t consisting of at least 1 and at most 2⋅105 lowercase Latin letters.

It is guaranteed that t is a subsequence of s.

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

Examples

input

bbaba
bb

output

3
原题链接

题意:

给出两个字符串a和b,b是a的一个子序列,要求删除a的一个最长子串使删除之后b仍是a的子串,求这个最长子串的长度

思路:

先来分析一下a,如果要删除a的一个子串无非是从两端开始删,和中间开始删如样例bbaba,删左端可以是b,右端可以是aba,中间可以是ba。
我们先来看中间,可以发现删去ba后左端的b又和右端的b接上了从而构成子序列的一部分,可以得出结论:若删除中间则删除的子串的左右两边对应一定是b字符串中的两个连续字符;
再来看两边,就简单多了,想要最大化删除,只需要寻找极值即可,删除右端需要找最左边的子序列,删除左端也一样。

代码:
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const ll maxn = 1e6 + 5;
string str1,str2;
ll book1[maxn],book2[maxn],ans;
int main()
{
    cin >> str1 >> str2;
    //寻找最左端子序列,把找出来的子序列存在book1中
    for(int i = 0, j = 0; i < str1.size(); i++)
    {
        if(str1[i] == str2[j] && j < str2.size())
            book1[j++] = i;
    }
    //寻找最右端子序列,同理
    for(int i = str1.size() - 1,j = str2.size() - 1; i >= 0; i--)
    {
        if(str1[i] == str2[j] && j >= 0)
            book2[j--] = i;
    }
    //求出左右端删除情况
    ans = str1.size() - book1[str2.size() - 1] - 1;
    ans = max(ans,book2[0]);
    //最大化中间删除,由于左右的极值序列已找出所以采用删除左边的i与右边的i+1之间的子串
    for(int i = 0; i < str2.size() - 1; i++)
        ans = max(book2[i + 1] - book1[i] - 1,ans);
    cout << ans << endl;
    return 0;
}

这里再解释一下最后一个操作,想要最大化中间删除只需要左极值序列删除右半部分和右极值序列删除左半部分即可例子。

ps.第一次写博客不足的地方还请大牛们指出
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值