Leetcode 3303. Find the Occurrence of First Almost Equal Substring

1. 解题思路

这道题的话思路上和上一题相仿,由于都是只能调整至多一个位置,因此,我们就是考察每一个位置前后最大的前序公共子序列以及后续的最大公共子序列的长度。

假设目标字符串word2的长度为 m m m,若某个位置与word2的最长公共前序数组的长度为 k k k

  • k ≥ m k\geq m km,那么该位置直接就是我们的一个答案
  • k < m k<m k<m,且从该位置开始的第 k + 2 k+2 k+2到第 m m m的恰好与word2的后 m − k − 1 m-k-1 mk1个字符相一致,那么通过调整第 k k k个字符,同样可以得到word2

由此,我们通过构造正向和负向的最大公共子串长度即可快速地求得任意一个位置是否满足条件,然后我们从中找到第一个符合题意的位置即可。

而对于任意方向的最大公共子串长度的计算方法,我们可以通过z算法进行实现,对应的内容网上有不少,我也写过一篇博客(经典算法:Z算法(z algorithm))对其进行简单介绍,这里就不过多展开了。

2. 代码实现

给出python代码实现如下:

def z_algorithm(s):
    n = len(s)
    z = [0 for _ in range(n)]
    l, r = -1, -1
    for i in range(1, n):
        if i > r:
            l, r = i, i
            while r < n and s[r-l] == s[r]:
                r += 1
            z[i] = r-l
            r -= 1
        else:
            k = i - l
            if z[k] < r - i + 1:
                z[i] = z[k]
            else:
                l = i
                while r < n and s[r-l] == s[r]:
                    r += 1
                z[i] = r-l
                r -= 1
    z[0] = n
    return z

class Solution:
    def minStartingIndex(self, s: str, pattern: str) -> int:
        n, m = len(s), len(pattern)
        z1 = z_algorithm(pattern + s)
        z2 = z_algorithm(pattern[::-1] + s[::-1])
        for i in range(n):
            if i+m > n:
                break
            c1 = z1[i+m]
            if c1 >= m:
                return i
            j = i+m-1
            c2 = z2[n-j-1+m]
            if c1 + c2 == m-1:
                return i
        return -1

提交代码评测得到:耗时2756ms,占用内存50.4MB。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值