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

时间:2017-12-01 12:41:23

标签: algorithm sorting dynamic-programming

我试图解决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 个答案:

答案 0 :(得分:3)

你真的不需要动态编程;你可以通过遍历字符串一次来完成它,并在每个字符之后,在字典中存储状态(到目前为止遇到的a,b和c的相对数量)。该字典具有最大大小N + 1,因此总时间复杂度为O(N)。

如果您发现字符串中的某个点存在例如比b更多5个,比b更多7个c,你在字符串的另一个点找到相同的情况,然后你知道这两个点之间的子串包含相同数量的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,11,0,0这样的状态来自所有三个数字。

我们最终会得到这些状态的字典及其出现的次数:

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

仅出现一次的状态不表示abc相等的子串,因此我们可以丢弃它们;然后,我们留下了这些重复的状态:

4, 2, 4  

如果状态发生两次,则这两个位置之间有1个abc相等的子串。如果状态发生4次,则它们之间有6个abc相等的子串;例如状态1,1,0发生在以下几点:

dab|d|acb|d|cd  

这4点中的2点之间的每个子串都是abc-equal:

d, dacb, dacbd, acb, acbd, d  

通常,如果状态出现n次,则表示1 + 2 + 3 + ... + n-1 abc-equal子串(或更容易计算: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