【发布时间】:2020-10-16 07:14:00
【问题描述】:
我试图解决一个算法问题。我想出了一个递归算法来解决这个问题。这是问题的链接:
https://codeforces.com/problemset/problem/1178/B
此问题并非来自当前正在进行的任何比赛。
我已经编写了我的算法并在几个测试用例上运行了它,结果证明它的计数超过了正确的数量。我一遍又一遍地思考我的过程,但找不到任何错误。我在下面写了我的算法(不是代码,只是我想到的递归函数)。请问我哪里出错了——我的思考过程中的错误是什么?
让我的递归函数被称为count,随着算法的进行,它采用以下三种形式中的任何一种。
- count(i,'o',0) = count(i+1,'o',0) [+ count(i+1,'w',1) --> iff (i)th 字符串的元素是'o']
- count(i,'w',0) = count(i+1,'w',0) [+ count(i+2,'o',0) --> iff (i)th and (第 i+1) 个元素都等于 'v']
- count(i,'w',1) = count(i+1,'w',1) [+ 1 + count(i+2,'w',0) - -> iff 第 (i) 和 (i+1) 个元素都等于 'v']
注意:如果满足箭头后提到的条件,将调用 [.](方括号)内的递归函数调用。)
解释:开发的递归函数背后的主要思想是计算给定序列的出现次数。 count 函数接受 3 个参数:
参数 1:我们当前所在的字符串的索引。
参数 2:我们正在寻找的模式(如果这个参数是 'o' 这意味着我们正在寻找字母 'o' - 即它在哪个索引处。如果它是 'w' 这意味着我们正在寻找模式“vv”——即我们正在寻找出现这种模式的 2 个连续索引。)
参数 3:这可以是 1 或 0。如果是 1,则意味着我们正在寻找 'vv' 模式,已经找到了 'o' 即我们正在寻找所示的 'vv' 模式粗体:vvovv。如果它是 0,这意味着我们正在搜索 'vv' 模式,这将是 模式的开头vvovv(以粗体显示。)
我将使用 count(0,'w',0) 启动算法——这意味着,我们在字符串的第 0 个索引处,我们正在寻找模式 'vv' , 而这个 'vv' 将是我们希望找到的 'vvovv' 模式的前缀。
所以,count(0,'w',0) 的输出应该是我的答案。现在麻烦来了,对于以下输入:“vvovooovovvovoovoovvvvovo”(比如 input1),我的程序(基于上述算法)给出了预期的答案(= 50)。但是,当我只是将“vv”附加到上述输入以获得新输入:“vvovooovovvovoovoovvvvovovv”(比如 input2)并再次运行我的算法时,我得到 135答案,而正确答案是 75(这是解决方案代码返回的答案)。为什么会这样?我在哪里出错了?
另外,还有一个疑问是,如果 input1 的输出是 50,那么 input2 的输出应该至少是正确的两倍——因为 input1 中存在的所有子序列都将出现在 input2 中同样,所有这些子序列也可以通过附加的“vv”形成一个新的子序列——这意味着我们至少有 100 个有利的子序列,对吧?
附:这是解决方案代码的链接https://codeforces.com/blog/entry/68534
【问题讨论】:
-
我发现了错误,我犯了。第三次递归应该是这样的: count(i,'w',1) = count(i+1,'w',1) [+ 1 --> iff (i)th 和 (i+1)th 元素是都等于'v']。因为,一旦我们找到了解决方案,我们只需要加 1(表示我们已经得到答案)并停止——我们不应该从那里进行任何递归调用,否则相同的子序列将被计算多次。
标签: algorithm recursion dynamic-programming