从S串变成T串
每个字符串中的字符要么是上个字符串的对应位置的字符,要么是这个字符串的左边一个的字符。
问要进行几次转化才能从S变成T
可以发现,其实就是如图所示的折线式的转移(注意不要被误导了,这是样例,但不是最优的转移方案)
或者说再看这一个图
由于c的折线和左边那个a有冲突,所以a只能延缓它右拐的时间
那我们具体怎么实现呢
这个折线只能拐右和向下
首先,我们只需要考虑连续的字符的最左端
对于T串上一个位置i
我们先求出当前还未被访问的,<=i的,S[p]==T[i]的最大的p
我们从大到小枚举i,然后从p到i,贪心地想,我们始终尽可能往右走
所以对于一条直线,它所对应的深度就是拐点数量+1
如何维护拐点呢
我们把之前的p压进队列
对于每个拐点来说,他的横向长度应该是1 是这样吗?存疑
所以这个点会影响到后面的,是这个点往前延伸队列大小那么多距离能到达当前的i
好像就讲完了?
反正我也还是很懵…
肯定是没讲清楚的…
#include
#include
#include
using namespace std;
const int N=1e6+5;
typedef long long ll;
char S[N],T[N];
int n;
int s,t,q[N];
int main()
{
scanf("%d",&n);
scanf("%s",S+1);
scanf("%s",T+1);
if(strcmp(S+1,T+1)==0){
puts("0");
return 0;
}
s=1,t=0;
int p=n;
int ans=0;
for(int i=n;i>=1;i--){
if(T[i]==T[i-1])
continue;
p=min(p,i);
while(p&&T[i]!=S[p])
p--;
if(!p){
puts("-1");
return 0;
}
while(s<=t&&q[s]-(t-s+1)+1>i)
s++;
q[++t]=p;
if(i!=p)
ans=max(ans,t-s+1);
}
printf("%d\n",ans+1);
}