1. 程式人生 > >AGC007 F Shik and Copying String

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); }