AGC007 F Shik and Copying String

題意

從S串變成T串
每個字符串中的字符要麼是上個字符串的對應位置的字符,要麼是這個字符串的左邊一個的字符。
問要進行幾次轉化才能從S變成T

題解在這裏插入圖片描述

可以發現,其實就是如圖所示的折線式的轉移(注意不要被誤導了,這是樣例,但不是最優的轉移方案)
或者說再看這一個圖
在這裏插入圖片描述
由於c的折線和左邊那個a有衝突,所以a只能延緩它右拐的時間

那我們具體怎麼實現呢
這個折線只能拐右和向下
首先,我們只需要考慮連續的字符的最左端
對於T串上一個位置i
我們先求出當前還未被訪問的,<=i的,S[p]==T[i]的最大的p
我們從大到小枚舉i,然後從p到i,貪心地想,我們始終儘可能往右走
所以對於一條直線,它所對應的深度就是拐點數量+1
如何維護拐點呢
我們把之前的p壓進隊列
對於每個拐點來說,他的橫向長度應該是1 是這樣嗎?存疑
所以這個點會影響到後面的,是這個點往前延伸隊列大小那麼多距離能到達當前的i
好像就講完了?
反正我也還是很懵…
肯定是沒講清楚的…

#include<cstdio>
#include<cstring>
#include<algorithm>
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);
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章