题目地址: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; } };
参考文章
扫描二维码关注公众号,回复:
10949003 查看本文章