466. Count The Repetitions
Hard
10279FavoriteShare
Define S = [s,n]
as the string S which consists of n connected strings s. For example, ["abc", 3]
="abcabcabc".
On the other hand, we define that string s1 can be obtained from string s2 if we can remove some characters from s2 such that it becomes s1. For example, “abc” can be obtained from “abdbec” based on our definition, but it can not be obtained from “acbbe”.
You are given two non-empty strings s1 and s2 (each at most 100 characters long) and two integers 0 ≤ n1 ≤ 106 and 1 ≤ n2 ≤ 106. Now consider the strings S1 and S2, where S1=[s1,n1]
and S2=[s2,n2]
. Find the maximum integer M such that [S2,M]
can be obtained from S1
.
Example:
Input: s1="acb", n1=4 s2="ab", n2=2 Return: 2
我发现我做题思路有点偏了。思路侧重于寻找特殊规律而不是一般规律,结果自然而然是不能AC。
这道题的暴力方法很简单,就是s1和s2循环遍历,每次遍历s1下标+1;只有当s1[i]==s2[j]时j++;如果i==len1;i=0;如果j==len2,则找到的次数加+1;时间复杂度是O(len1*n1);
因为[s1,n1]这个字符串是s1的n1次重复,所以有一些重复的模式在里面,主要是找到这个重复的模式,就可以省去重复模式的遍历;
举个例子:
0 1 2 3 0 1 2 3 0 1 2 3 0
S1 --------------> abacb | abacb | abacb | abacb | abacb | abacb
repeatCount -----> 0 | 1 | 1 | 2 | 2 | 3
Increment of
repeatCount -> 0 | 1 | 0 | 1 | 0 | 1
nextIndex -------> 2 | 1 | 2 | 1 | 2 | 1
^
|
repetitive pattern found here (we've met 2 before)!
The pattern repeated 3 times
所以只要当某个nextindex出现第二次,就可以判断重复模式出现。
所以n1段s1可以分为prefixseg,repeatseg,suffixseg.
这里有个小技巧:将哪几段划分为重复模式?假设第k段的nextindex在第i段已经出现过一次, 我第一次的做法是将[i,k-1]段划为重复模式,当计算repeatseg的不同part时第一part和第二part的重复次数不一样。
第一part为[i,k-1] 重复次数 = repeatcnt[k-1] - repeat[i-1];
第二part为[k,2k-i-1] 重复次数 = repeatcnt[2k-i-1] - repeatcnt[k-1];
第三part为[2k-i,3k-2i-1] 重复次数 = repeatcnt[3k-2i-1] - repeatcnt[2k-i-1];
因为nextindex[i-1]≠nextindex[k-1]=nextindex[2k-i-1]
所以repeatcnt[i]-repeatcnt[i-1] ≠repeatcnt[k]-repeatcnt[k-1]=repeatcnt[2k-i]-repeatcnt[2k-i-1];
所以不能将[i,k-1]划为重复模式,而是将[i+1,k]划为重复模式;
在判断第k段的nextindex是否已经出现过的时候,需要查找之前的nextindex,如果是向量的话,查找次数为O(n),这里可以采用哈希表(unordered_map)可以在O(1)时间内找到。
class Solution {
public:
int getMaxRepetitions(string s1, int n1, string s2, int n2)
{
int len1 = s1.size();
int len2 = s2.size();
unordered_map<int,int> repeatcnt;
unordered_map<int,int> nextindex;
int j = 0, cnt =0;
int prefixcnt = 0, middlecnt = 0, suffixcnt = 0;
for(int k=1;k<=n1;k++)
{
for(int i=0;i<len1;i++)
{
if(s1[i]==s2[j])
j++;
if(j == len2)
{
j = 0;
cnt++;
}
}
if(nextindex.count(j) > 0 )
{
int i = nextindex[j];
prefixcnt = repeatcnt[i];
middlecnt = (n1-i)/(k-i)*(cnt-repeatcnt[i]);
suffixcnt = repeatcnt[i+(n1-i)%(k-i)] - repeatcnt[i];
return (prefixcnt+middlecnt+suffixcnt)/n2;
}
repeatcnt[k] = cnt;
nextindex[j] = k;
}
return repeatcnt[n1]/n2;
}
};