D1. Remove the Substring (从easy到hard)

\(对于easy版本\)

\(直接枚举删掉的区间[l,r]判断是否存在t子串\)

\(这个很简单很暴力\)

#include <bits/stdc++.h>
using namespace std;
const int maxn=209;
char s[maxn],t[maxn];
int ans;
bool isok(int l,int r)
{
	int x=1;
	for(int i=1;i<=strlen(s+1);i++)
	{
		if(i>=l&&i<=r)	continue;
		if(t[x]==s[i])	x++;
		if(x==strlen(t+1)+1)	return true;
	}
	return false;
}
int main()
{
	cin>>(s+1)>>(t+1);
	for(int i=1;i<=strlen(s+1);i++)
	for(int j=i;j<=strlen(s+1);j++)
		if(isok(i,j))	ans=max(ans,j-i+1);
	cout<<ans;
}

\(\color{red}hard版本\)

\(我们知道,区间最大有两种情况\)

\(一、首字符出现最晚,此时删掉[1,首字符)\)

\(末字符出现最早,此时删掉(末字符,n](n是s串长度)\)

\(二、当最快匹配到i位置时,下一个匹配的字母使其最远为j,此时可删掉(i,j)\)

\(\color{Red}这些都不难想,包括最快匹配到i字符的位置\)

\(最快,所以我们一个字符一个字符匹配,相同就往后匹配\)

\(那如何知道下一个字母最晚能在哪里匹配呢?\)

\(\color{orange}我们只需要倒着求一遍倒着的t串最快匹配位置即可\)

#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
char s[maxn],t[maxn];
int pre[maxn],last[maxn],top1,top2,ls,lt,ans;
void isok1()
{
	int x=1;
	for(int i=1;i<=ls;i++)
	{
		if(s[i]==t[x])	pre[x++]=i;
		if(x>lt)	return;
	}
}
void isok2()
{
	int x=lt;
	for(int i=ls;i>=1;i--)
	{
		if(s[i]==t[x])	last[x--]=i;
		if(x<1)	return;
	}
}
int main()
{
	cin>>(s+1)>>(t+1);
	ls=strlen(s+1),lt=strlen(t+1);
	isok1();isok2();
	ans=max(last[1]-1,ls-pre[lt]);
	for(int i=1;i<lt;i++)
		ans=max(ans,last[i+1]-pre[i]-1);
	cout<<ans;
}
posted @ 2020-05-25 16:34  倾叶子佮  阅读(143)  评论(0编辑  收藏  举报