D2. Remove the Substring (hard version)
theme:给定一个串s和它的某个子序列t,现除去s中的一段子串,使得t仍然为s的子序列,问最大能删除多长的子串。|t|<=|s|<=2e5
solution:设t中字符分别为t0t1...tn,则最大值肯定在去除s中最右边满足能形成子序列t的t0之前字符、s中最左边满足能形成子序列t的tn之后的字符、或满足条件的最左边ti与最右边ti+1,的最大值。
所以我们的任务就是预处理出t中每个字符在s中能作为子序列的最左边与最右位置。算最左位置时我们只要按在t中的顺序从左到右找到第一个在s中的位置即可。由于在算ti时已确定了ti-1的位置,所以保证当前的si一定可以构成子序列。求最右最大时从右往左遍历即可。
#include<bits/stdc++.h>
#include<vector>
#include<algorithm>
#define far(i,t,n) for(int i=t;i<n;++i)
#define pb(a) push_back(a)
#define lowbit(x) x&(-x)
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
int inf=0x3f3f3f3f;
int mod=998244353;
const int maxn=200010;
char s[maxn],t[maxn];
int l[maxn],r[maxn];
int main()
{
cin>>s>>t;
int ls=strlen(s),lt=strlen(t);
for(int i=0,j=0;i<ls&&j<lt;++i)
if(s[i]==t[j])
l[j++]=i;
for(int i=ls-1,j=lt-1;i>=0&&j>=0;--i)
if(s[i]==t[j])
r[j--]=i;
int ans=r[0];
far(i,1,lt)
ans=max(ans,r[i]-l[i-1]-1);
ans=max(ans,ls-l[lt-1]-1);
cout<<ans<<endl;
}