在包含相等数量 a、b、c 的字符串中查找子串的数量

Posted

技术标签:

【中文标题】在包含相等数量 a、b、c 的字符串中查找子串的数量【英文标题】:Find the number of substrings in a string containing equal numbers of a, b, c 【发布时间】:2017-12-01 12:41:23 【问题描述】:

我正在尝试解决this problem。现在,我能够得到一个递归解决方案:

如果DP[n]给出了以字符串的第n个字符结尾的漂亮子字符串的数量(在问题中定义),那么为了找到DP[n+1],我们从第(n+1)个字符向后扫描输入字符串直到我们找到一个第 i 个字符,使得从第 i 个字符开始到第 (n+1) 个字符结束的子字符串是美丽的。如果找不到这样的我,DP[n+1] = 0

如果找到这样的字符串,则DP[n+1] = 1 + DP[i-1]

问题是,这个解决方案在一个测试用例上给出了超时。我怀疑是 向后扫描 部分有问题。我的解决方案的整体时间复杂度似乎是O(N^2)。输入数据的大小似乎表明该问题需要O(NlogN) 解决方案。

【问题讨论】:

【参考方案1】:

您实际上并不需要为此进行动态编程;您可以通过遍历字符串一次并在每个字符之后将状态(到目前为止遇到的 a、b 和 c 的相对数量)存储在字典中来实现。该字典的最大大小为 N+1,因此总体时间复杂度为 O(N)。

如果你发现在字符串的某个点有例如a 比 b 多 5 个,c 比 b 多 7 个,并且您在字符串的另一点发现相同的情况,那么您知道这两个点之间的子字符串包含相同数量的 a、b 和 c。

让我们看一个输入“dabdacbdcd”的例子:

       a,b,c

   ->  0,0,0  
d  ->  0,0,0  
a  ->  1,0,0  
b  ->  1,1,0  
d  ->  1,1,0  
a  ->  2,1,0  
c  ->  2,1,1  ->  1,0,0  
b  ->  1,1,0  
d  ->  1,1,0  
c  ->  1,1,1  ->  0,0,0    
d  ->  0,0,0  

因为我们只对 a、b'a 和 c 的数量之间的差异感兴趣,而不是实际数量,所以我们通过从所有三个数字中减去最小的数字来将 2,1,1 之类的状态减少到 1,0,0 .

我们最终得到了这些状态的字典,以及它们出现的次数:

0,0,0  ->  4  
1,0,0  ->  2  
1,1,0  ->  4  
2,1,0  ->  1  

只出现一次的状态并不表示一个 abc-equal 子串,所以我们可以丢弃它们;然后我们就剩下这些重复的状态:

4, 2, 4  

如果一个状态出现两次,那么这两个位置之间有 1 个 abc-equal 子串。如果一个状态出现 4 次,则它们之间有 6 个 abc 相等的子串;例如状态 1,1,0 出现在这些点:

dab|d|acb|d|cd  

这 4 个点中的 2 个之间的每个子字符串都是 abc 相等的:

d, dacb, dacbd, acb, acbd, d  

一般来说,如果一个状态出现n次,它代表1 + 2 + 3 + ... + n-1个abc相等的子串(或者更容易计算:n-1 × n/2)。如果我们为字典中的每个计数计算这个,总数就是我们的解决方案:

4  ->  3 x 2 = 6  
2  ->  1 x 1 = 1  
4  ->  3 x 2 = 6  
              --
              13  

让我们通过找出这 13 个子字符串来检查结果:

 1  d---------  
 2  dabdacbdc-  
 3  dabdacbdcd  
 4  -abdacbdc-  
 5  -abdacbdcd  
 6  --bdac----  
 7  ---d------  
 8  ---dacb---  
 9  ---dacbd--  
10  ----acb---  
11  ----acbd--  
12  -------d--  
13  ---------d  

【讨论】:

感谢您的精彩解释。你能在这条线上解释更多吗? “一般来说,如果一个状态出现n次,它代表1 + 2 + 3 + ... + n-1个abc-equal子串(或者更容易计算:n-1 × n/2)”

以上是关于在包含相等数量 a、b、c 的字符串中查找子串的数量的主要内容,如果未能解决你的问题,请参考以下文章

怎么查找一个string 字符串中的子字符串出现的次数和位置

shell怎么查找子字符串出现的位置

查找给定字符串的所有前缀的最长回文子串的长度

字符串中数字子串的求和

牛客多校2018第一场 I Substring (不同子串的个数)

字符串