【AGC007F】Shik and Copying String【贪心】【队列】

画一个折线图。每一行表示一次复制,每一列表示一个位置,红线表示字母确定过程的路线。
【AGC007F】Shik and Copying String【贪心】【队列】_第1张图片
则我们可以从T串从右往左贪心取,使得折线尽量靠右。可以证明这样子是最优的。
具体实现时,我们可以维护一个队列,里面存在若干的T中的位置和S中匹配尽量靠后匹配位置的最大值,而且要满足这些位置和当前位置是相互影响的,也就是两个位置的折线会交在一起。这样子我们就要开队列大小+1层,使得不会冲突。

#include
#include
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
const int N=1000005;
int n,pos,ans,head,tail,q[N];
char s[N],t[N];
int main(){
    scanf("%d%s%s",&n,s+1,t+1);
    if(!strcmp(s+1,t+1)){
        puts("0");
        return 0;
    }
    pos=n;
    head=1,tail=0;
    for(int i=n;i>=1;i--){
        if(t[i]==t[i-1]){
            continue;
        }
        pos=min(pos,i);
        while(pos&&t[i]!=s[pos]){
            pos--;
        }
        if(!pos){
            puts("-1");
            return 0;
        }
        while(head<=tail){
            if(q[head]-(tail-head+1)+1>i){
                head++;
            }else{
                break;
            }
        }
        q[++tail]=pos;
        if(i!=pos){
            ans=max(ans,tail-head+1);
        }
    }
    printf("%d\n",ans+1);
    return 0;
}

你可能感兴趣的:(贪心,队列)