AGC007 F Shik and Copying String

题意

从S串变成T串
每个字符串中的字符要么是上个字符串的对应位置的字符,要么是这个字符串的左边一个的字符。
问要进行几次转化才能从S变成T

题解AGC007 F Shik and Copying String_第1张图片

可以发现,其实就是如图所示的折线式的转移(注意不要被误导了,这是样例,但不是最优的转移方案)
或者说再看这一个图
AGC007 F Shik and Copying String_第2张图片
由于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);
}

你可能感兴趣的:(AGC)