快速判断两个字符串是否相等:字符串哈希

LeetCode 2430. 对字母串可执行的最大删除数

给你一个仅由小写英文字母组成的字符串 s 。在一步操作中,你可以:

  • 删除 整个字符串 s ,或者
  • 对于满足 1 < = i < = s . l e n g t h / 2 1 <= i <= s.length / 2 1<=i<=s.length/2 的任意 i ,如果 s 中的 前 i 个字母和接下来的 i 个字母 相等 ,删除 前 i 个字母。

例如,如果 s = “ababc” ,那么在一步操作中,你可以删除 s 的前两个字母得到 “abc” ,因为 s 的前两个字母和接下来的两个字母都等于 “ab” 。
返回删除 s 所需的最大操作数。
提示:

  • 1 < = s . l e n g t h < = 4000 1 <= s.length <= 4000 1<=s.length<=4000
  • s 仅由小写英文字母组成

思路

首先一个字符串至少可以通过一次操作使其变成空串。那么如果需要最大化操作次数,就需要尽可能多的使用操作2。如果当前字符串s的某个前缀s[1,i]=s[i+1,2*i]相同的话,那么可以通过操作2来删除前i个字符。可以对于字符串s,可能存在多种方案使其删除某个前缀,但是对于每种方案都可能对后续产生不同的影响,所以此时使用记忆化搜索来求解。但对于每一次记忆化搜索,都需要在 O ( 1 ) O(1) O(1)的时间复杂度下快速判断某个前缀子字符串与后续的子字符串是否相等,此时可以使用字符串哈希来快速判断。字符串哈希就是将字符串当作一个P进制数,然后将其转化为10进制数来计算某个前缀的哈希值。计算某个子字符串s[i,j]的哈希值时,可通过 f [ j ] − f [ i − 1 ] ∗ P j − i + 1 f[j]-f[i-1]*P^{j-i+1} f[j]f[i1]Pji+1来快速计算,从而快速实现字符串的比较。

代码

class Solution {

    long[] f, p;
    int P = 131;
    int n;
    int[] ff;

    public int deleteString(String s) {
        n = s.length();
        f = new long[n+1];
        p = new long[n+1];
        ff = new int[n];
        init(s);
        return dfs(s,0);
    }

    public void init(String s) {
        p[0] = 1;
        for(int i = 1; i <= n; i++) {
            f[i] = f[i-1] * P + s.charAt(i-1);
            p[i] = p[i-1] * P;
        }
    }

    public int dfs(String s, int u) {
        if(u == n) {
            return 0;
        }
        if(ff[u] != 0) {
            return ff[u];
        }
        int len = n - u;
        ff[u] = 1;
        for(int i = 1; i <= len / 2; i++) {
            if(get(u+1,u+i) == get(u+i+1,u+2*i)) {
                ff[u] = Math.max(ff[u], dfs(s,u+i) + 1);
            }
        }
        return ff[u];
    }

    public long get(int a, int b) {
        return f[b] - f[a-1] * p[b-a+1];
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值