zoukankan      html  css  js  c++  java
  • AT2173

    一道乱搞的题...

    题意:给你两个字符串,每次操作步骤如下:从前向后扫描整个字符串,对于每一位都有两种选择,一种是保持原来的字符不变,另一种是把这一位上的字符变成和前一位一样(注意是操作后的前一位),问你至少需要多少次操作才能将第一个字符串变成第二个字符串,如果不可能输出-1

    题解:

    看到网上所有人都在说“画一画就好”,然而我这种蒟蒻根本不会画啊喂!!!

    因此这篇博客的目的在于...谈一谈怎么画...

    首先我们不难看到:最佳的方法一定是从后向前修改(因为如果从前向后修改,很有可能把要用的字符覆盖掉了,这样就无法成功覆盖了)

    接下来,我们维护一个单调递减的变量$posi$,用于记录上一个先前最早匹配的位置在哪

    可能这句话并不好理解,我们举个例子讲:

    比如原串是$acbaba$,而目标串是$acbacb$,那么合理的对应方式应当是这样的:

    可以看到,虽然4号位置上的$a$之前最近的就是自己上面的$a$,但是不能直接继承,因为5号位上的$c$已经把匹配位置放到2了,为了保证正确覆盖,必须用之前的$a$,这也就导致了前面的无法匹配,所以这是一个无解情况!

    那么我们回到有解的情况:

    如果有解的话,显然原串中的每一个点最后会覆盖到目标串上的一段区间(废话),那么我们取出这个区间的最左端点来研究即可。

    不难发现,每一个值在覆盖的时候一定是一种折线的形式!

    举个例子:

    这是一个例子的部分情况

     可以发现:为了覆盖上那三个$a$,我们应该用原来的$a$覆盖整个区间

    但是为了避免中间的位置被错误覆盖导致这之后的位置被覆盖,所以我们应该用中间的位置覆盖再去覆盖后面的位置!

    举个例子:

    $s="abcde",t="aaacc"$

    为了防止a开始覆盖后覆盖掉了c导致后面无法被覆盖,我们要先用c去覆盖

    所以针对a而言,它的覆盖过程更应该是一条折线!

    或者,应该是这样:

    每次向前拓展了一个部分,直到能覆盖上目标即可。

    因此,我们只需要求出这样的折线最多折了几次就是答案!

    怎么求?

    我们开一个队列,队列里储存这样的折线中需要折的每个位置(也即一个位置对应一次偏折),那么队列的大小即为偏折的次数

    然后每次将无用的位置弹出队列即可。

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    using namespace std;
    char s[1000005],t[1000005];
    queue <int> Q;
    int n;
    bool check()
    {
        for(int i=1;i<=n;i++)if(s[i]!=t[i])return 0;
        return 1;
    }
    int main()
    {
        freopen("game.in","r",stdin);
        freopen("game.out","w",stdout);
        scanf("%d",&n);
        scanf("%s%s",s+1,t+1);
        if(check()){printf("0
    ");return 0;}
        int posi=n;
        int ans=0;
        for(int i=n;i>=1;i--)
        {
            if(t[i]==t[i-1])continue;
            posi=min(posi,i);
            while(posi&&t[i]!=s[posi])posi--;
            if(!posi){printf("-1
    ");return 0;}
            while(!Q.empty())
            {
                if((int)Q.front()-(int)Q.size()>=i)Q.pop();
                else break;
            }
            Q.push(posi);
            if(i!=posi)ans=max(ans,(int)Q.size());
        }
        printf("%d
    ",ans+1);
        return 0;
    }
  • 相关阅读:
    Jmeter使用自定义编写代码
    Jmeter关于断言
    Jmeter之函数助手
    无界面运行Jmeter压测脚本 --后知者
    接口测试全流程总结
    全面的功能测试点总结
    简述核心网
    题1:一个手机H5测试页面,页面上有一个文本输入框和一个次数的按键---测试用例编写
    2019 版_Python 常见的 170 道面试题全解析:编码规范
    2019 版_Python 常见的 170 道面试题全解析:语言特性
  • 原文地址:https://www.cnblogs.com/zhangleo/p/10853306.html
Copyright © 2011-2022 走看看