zoukankan      html  css  js  c++  java
  • 滑动

    Seek the Name, Seek the Fame

    先看一下KMP核心的next数组的操作:

    nex[0] = -1;
    for (i = 1; i <= len; i++)
    {
        while (j >= 0 && st[j + 1] != st[i]) //不匹配回溯一个大规律
            j = nex[j];
        nex[i] = ++j;   //经过上面的循环,要么j回到了0,要么已经重新回到了st[j+1]==st[i]可以继续匹配啦
    }
    
    如串a b a b a c
    下标1 2 3 4 5 6
    j        匹配       回溯        nex[1]=0
    0   ([1]a!=[2]b)    -1             2=0
    0    ([1]a=[3]a)    No             3=1
    1    ([2]b=[4]b)    No             4=2
    2    ([3]a=[5]a)    No             5=3
    3   ([4]b!=[6]c)     2
    2   ([2]b!=[6]c)    -1             6=0
     可以得到:
              串 a b a b a c
            下标 1 2 3 4 5 6
        next数组 0 0 1 2 3 0
         如当下标为5不匹配时,我们将直接回溯到下标[3-1]的[2]b上
                下标为6不匹配时,我们将回溯到[1]a上从新开始
     
    KMP就可以通过快速的段级的回溯减少大量匹配操作。

    看一道例题——2021年广东工业大学第十五届文远知行杯程序设计竞赛-B题找山坡

    链接:https://ac.nowcoder.com/acm/contest/13504/B

    计算:

    max{ R - L | 1 <= L <= R <= n, a[L] == a[R], 对于所有i (L <= i <= R), 满足a[i] >= a[L] }.
    找到两个坐标,这两个坐标的值相等,并且他们之间的值都大于等于这两个坐标上的值.
    这两个坐标相减最大能是多少.

    样例输入:

    5
    1 2 3 2 1

    样例输出:

    4   ( [5]1 - [1]1 = 4 )

        ans = 0,j=0;
        for (i = 1; i <= n; i++)
        {
            while (j && a[nex[j]] > a[i])//遇到a[i]变小,前推nex[j],扩大区间
    j--; if (j && a[nex[j]] == a[i]) //匹配值等于a[i]时,取最大区间 ans = max(ans, i - nex[j]); else nex[++j] = i; }

    如:

    5
    1 2 3 2 1

    我们第一次匹配到的应该是         [2]2  = [4]2   ans=2

    然后会有[5]1 < [4]2   nex[j]前推   [1]1  = [5]1   ans=4

    看大佬写的题解,他们好像是一类问题,可以用单调栈/单调队列乱杀。待我学习补充..

  • 相关阅读:
    MQTT初步使用
    越简单越喜欢
    大端小端
    Chapter 21_5.2 tab扩展
    Chapter 21_5.1 URL编码
    Chapter 21_5 替换
    插件api
    怎么找到一个好名字idea插件开发
    Struts2 maven项目简单案例
    javassist_1 cannot be cast to jaassist.util.proxy.Proxy
  • 原文地址:https://www.cnblogs.com/thx2199/p/14588988.html
Copyright © 2011-2022 走看看