[每日算法]1668. 最大重复子字符串

一、题目

        给你一个字符串 sequence ,如果字符串 word 连续重复 k 次形成的字符串是 sequence 的一个子字符串,那么单词 word 的 重复值为 k。单词 word 的 大重复值 是单词 word 在 sequence 中最大的重复值。如果 word 不是 sequence 的子串,那么重复值 k 为 0 。

        给你一个字符串 sequence 和 word ,请你返回 最大重复值 k

提示:

  • 1 <= sequence.length <= 100
  • 1 <= word.length <= 100
  • sequence 和 word 都只包含小写英文字母。

二、解题思路

        这道题的解题方式很多,dp算法,kmp算法都可以求解,今天我们学习一个比较新颖的思路解决这道题。

        仔细想这道题的解题思路,如果用暴力求解,每次从长串中获取一个短串,每次都比较截取串和target串之间是否相同,如果相同则会追加一个次数,到sequence[i-word.length]的dp数组位置。之所以需要一个dp数组,因为题目要求的是不能重叠的 连续重复 k 次。所以我们每次取值都需要考虑【连续】和【最大】两个因变量。

        今天的方法叫做【字符串哈希算法】,基本思想就是基于小串长度,计算每一个该小串的hashCode值。这个值要解决hash冲突。由于两个字符串的长度都不超过100个,用例范围不多。我们尽可能取1,331、131这种较大质数避免因为hash冲突无法通过。

        如何计算小串长度的hashCode呢?

        我们参考10进制计算方式

        如果有abcd这么一个字符串,如果换算成十进制我们应该是这么算的

A[0]=a*10^0;

A[1]=(A[0])*10+b*10^0= a*10+b;

A[2]=(A[1]*10)+c=a*10^2+b*10^1+c;

A[3]=(A[2])*10+d;

所以最终的等式为:

a*10^3+ b*10^2+c*10+d;

        那么如果我们小串是cd,cd的值应该是c*10+d,这个求解是怎么来的呢?

        我们继续从头到尾求每一个位置10进制的个数

P[0]=1;

P[1]=10;

P[2]=100

P[3]=1000

B=c10+d = A[3]-P2*(a*10+b) = A-P2*A[1] ;

        所以我们要求一个小串的hashCode,就要求前缀A数组和进位数组P.

        在遍历字符串sequence的过程中,如果发现以i为结尾的小串hashCode跟word字符串的hashCode相等

则dp[i]=dp[i-word.length]+1;

而求以i为结尾小串的hashCode为:

A[i]-P[word.lengh]*A[i-word.length];

        另外为了简化计算,A数组 和P数组长度都sequence.length()基础上增加1,这样在求小串hashCode的时候要调整遍历的位置从0---》sequence.length()-1 变为1--》sequence.length()

三,代码示例

  public int maxRepeating1(String sequence, String word) {
        int sLen =sequence.length();
        int wLen= word.length();
        int len =sLen+wLen+1;
        String s=sequence+word;
        //hashcode前缀数组
        long[] A = new long[len];
        //进位数组
        long[] P = new long[len];
        int[] dp = new int[len];
        //尽量选大质子,避免hash冲突
        int factor=131;
        int max = 0;
        P[0]=1;
        for(int i=1;i<len;i++){
            A[i]=A[i-1]*factor+s.charAt(i-1);
            P[i]=P[i-1]*factor;
        }
        //求小串的hashcode
        long destination = A[len-1]-A[len-wLen-1]*P[wLen];
        //遍历A的位置为1--》sequence.length()
        for(int i=1;i<=sequence.length();i++){
            if(i-word.length()<0){
                continue;
            }else {
                long temp =   A[i]-A[i-wLen]*P[wLen];
                if(temp==destination){
                    dp[i]=dp[i-wLen]+1;
                    max= Math.max(max,dp[i]);
                }
            }
        }

        return max;
    }

四、复杂度分析

时间复杂度是O(m+n) m=sequence.length n=word.length

空间复杂度O(m+n)

感谢收看~

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值