Algorithm 计算形成字符串连续子串的有序且可能不连续的子串的数量
假设S(N)是长度为N的字符串“012…”,其中“012”重复,直到有N个字符 对于任意给定的N,通过按顺序从字符串中选择可能不连续的字母,计算形成连续子字符串的方式的数量 例如,对于N=5,我们有S(N)=“01201” 连续子字符串和计数:Algorithm 计算形成字符串连续子串的有序且可能不连续的子串的数量,algorithm,dynamic-programming,Algorithm,Dynamic Programming,假设S(N)是长度为N的字符串“012…”,其中“012”重复,直到有N个字符 对于任意给定的N,通过按顺序从字符串中选择可能不连续的字母,计算形成连续子字符串的方式的数量 例如,对于N=5,我们有S(N)=“01201” 连续子字符串和计数: '0', 2 '1', 2 '2', 1 '01', 3 (the two consecutive '01' along with the first and last character of '01201'). '12', 1 '20', 1 '01
'0', 2
'1', 2
'2', 1
'01', 3 (the two consecutive '01' along with the first and last character of '01201').
'12', 1
'20', 1
'012', 1
'120', 1
'201', 1
'0120', 1
'1201', 1
'01201', 1
Total: 16
对于任意N,我们如何有效地计算它?我将发布我的最佳答案作为解决方案
请注意,这个问题最初来自Cococino223,但措词不当,在修复之前就被删除了。假设f(n)是n的计数,f(n,k)是{0,1,2}中以k代表k结尾的子字符串中的n的计数
N f(n, 0) f(n, 1) f(n, 2) f(n)
0 0 0 0 0
1 1 0 0 1
2 1 2 0 3
3 1 2 3 6
4 5 2 3 10
5 5 8 3 16
6 5 8 12 25
7 18 8 12 38
8 18 27 12 57
9 18 27 40 85
10 59 27 40 126
11 59 87 40 186
方法:f(n,k)只有在第n个字符串以k结尾时才改变。在这种情况下:
f(n, k) = f(n-1, k) + f(n-1, k') + 1
Where k' is the predecessor of k in '012' with wraparound.
E.g., f(6,2) = 12 = f(5,2) + f(5,1) + 1
这里的直觉是,我们有所有以k结尾的方式,它们不使用最新的字母(f(n-1,k)),所有使用最新的k的方式,它们必须等于在序列中使用前一个字母的所有方式,在末尾加上k(f(n-1,k'),再加上一个新的k(+1)
这是线性时间,恒定的记忆
--更新——如果你读到了变化的数字:1,2,3,5,8,12,18,27,40,59,87,128,188,276,405,594,871,这是
--更新--
调用M上面的平方矩阵,然后我们可以用M来计算k的连续值。例如,[12,18,27,1]*M=[18,27,40,1]
我们可以通过反复平方矩阵,在对数时间内用它来求解f(n)
E.g. M^8 = [4, 6, 9, 0]
[3, 4, 6, 0]
[6, 9, 13, 0]
[12, 18, 27, 1]
[0, 0, 0, 1] * M^8 = [12, 18, 27, 1]
12 + 18 + 27 = 57 = f(8)
f(n)是M^n最下面一行的前三个元素之和
所以f(n)可以在对数时间内计算,但因为矩阵mult相当昂贵,这只对相对较大的n有意义。请注意,这适用于不是2的幂的数字,方法是将适当的2的幂的矩阵相乘。例如,13=1101,所以我们乘(M^1)(M^4)(M^8)。我想知道重复的矩阵平方法是否可以将其降到对数时间(类似于斐波那契)。
E.g. M^8 = [4, 6, 9, 0]
[3, 4, 6, 0]
[6, 9, 13, 0]
[12, 18, 27, 1]
[0, 0, 0, 1] * M^8 = [12, 18, 27, 1]
12 + 18 + 27 = 57 = f(8)