面试题466:统计重复个数(C++)

题目地址:https://leetcode-cn.com/problems/count-the-repetitions/

题目描述

由 n 个连接的字符串 s 组成字符串 S,记作 S = [s,n]。例如,["abc",3]=“abcabcabc”。

如果我们可以从 s2 中删除某些字符使其变为 s1,则称字符串 s1 可以从字符串 s2 获得。例如,根据定义,"abc" 可以从 “abdbec” 获得,但不能从 “acbbe” 获得。

现在给你两个非空字符串 s1 和 s2(每个最多 100 个字符长)和两个整数 0 ≤ n1 ≤ 106 和 1 ≤ n2 ≤ 106。现在考虑字符串 S1 和 S2,其中 S1=[s1,n1] 、S2=[s2,n2] 。

请你找出一个可以满足使[S2,M] 从 S1 获得的最大整数 M 。

题目示例

示例:

输入:
s1 ="acb",n1 = 4
s2 ="ab",n2 = 2

返回:2

解题思路

思路1:分析题目可知,字符串S1是由n1个s1连接而成,字符串S2是由n2个s2连接而成,求满足使[S2,M]从S1获得的最大整数M,有点绕口,通俗说,即求S1中包含S2的个数M。最容易想到的方法是初始化M=0,然后遍历S1寻找S2,找到S2后M++,依次继续,直到S1遍历结束。当然,需要注意遍历的条件,即保证S2的长度应该小于等于S1的长度。不过可惜的是,这种思路导致超时问题。

思路2:如果s2在S1中出现了N次,那么S2肯定在S1中出现了N/n2次,这里的大写表示字符串加上重复次数组成的大字符串,即字符串拼接结果。所以,我们只要算出s2出现的次数count_s2,然后除以n2,就可以得出S2在S1中出现的次数了,即可求得M。

程序源码

暴力(超时

class Solution {
public:
    int getMaxRepetitions(string s1, int n1, string s2, int n2) {
       string S1 = "", S2 = "";
        int M = 0;
        for(int i = 0; i < n1; i++) S1 += s1;
        for(int j = 0; j < n2; j++) S2 += s2;
        int k = 0;
        for(int i = 0; i < S1.size(); i++)
        {
            if(S1[i] == S2[k]) k++;
            if(k == S2.size())
            {
                M++;
                k = 0;
            }
        }
        return M;
    }
};

思路2:暴力优化

class Solution {
public:
    int getMaxRepetitions(string s1, int n1, string s2, int n2) {
       int s2_next_index = 0, count_s1 = 0, count_s2 = 0;
       unordered_map<int, pair<int, int>> mp;
       while(count_s1 < n1)
       {
           for(int i = 0; i < s1.size(); i++)
           {
               if(s1[i] == s2[s2_next_index]) s2_next_index++;
               if(s2_next_index == s2.size())
               {
                   s2_next_index = 0; //下一轮循环
                   count_s2++;
               }
           }
           count_s1++;
           if(mp.count(s2_next_index) == 0) mp[s2_next_index] = make_pair(count_s1, count_s2);
           else 
           {
               int last_count_s1 = mp[s2_next_index].first;
               int last_count_s2 = mp[s2_next_index].second;
               int interval_s1 = count_s1 - last_count_s1;
               int interval_s2 = count_s2 - last_count_s2;
               int num = (n1 - count_s1) / interval_s1;
               count_s2 += num * interval_s2;
               count_s1 += num * interval_s1;
           }
       }
       return count_s2 / n2;
    }
};

参考文章

https://www.cnblogs.com/grandyang/p/6149294.html

https://leetcode-cn.com/problems/count-the-repetitions/solution/fang-zhao-yi-ge-da-lao-xie-de-by-paul_666/

----------------------------------- 心之所向,素履所往;生如逆旅,一苇以航。 ------------------------------------------
原文地址:https://www.cnblogs.com/wzw0625/p/12731463.html