给出一个数字字符串,例如"12335457"
。有效分区是字符串的分区,因此每个段都严格大于前一个段。
例如,"12 | 33 | 54 | 57"
是有效分区,而57 > 54 > 33 > 12
是有效分区。另一个有效分区可以是"12 | 335 | 457"
。
给定的字符串可能有多少个有效分区?字符串的最大长度可以为5000
。
如果我们使用带有参数i
和j
的动态编程,这意味着最后一段来自i ... to ..j
,那么我们可以递归其余部分。
int solve(int i,int j) {
// memoization need to be added
int last_length = j - i + 1;
int ans = 0;
for(int k = j + last_length ; k < n ; k++) {
if( segment(j+1,k) > segment(i,j) ) { // this is possible in O(1) even if segment lengths are equal
// we should do some pre preocessing on the given string
// which can take O(n^2) time
// if segment(j+1,k) length is more than L , then it is trivial
ans += solve(j+1 , k);
}
}
}
但是这种方法将花费O(n ^ 3)的时间。如何从O(n ^ 3)减少它?
谢谢
答案 0 :(得分:1)
观察:
sudo apt-get install python-dev
的最小值index
称为segment(j + 1 , index) > segment(i, j)
,我们可以看到x
所以,让我们叫solve(i, j) = sum( solve(j + 1, k) ) with x <= k < n
,我们有我们的功能:
dp[i][j] = sum(solve[i][k]) with j <= k < n
最后一个问题是如何计算int solve(int i,int j) {
// memoization need to be added
int last_length = j - i + 1;
int ans = 0;
int index = getMinIndexForSegment(i,j)
ans = solve(j + 1, index) + solve(i, j + 1);
return ans;
}
?我们意识到我们可以使用二进制搜索来快速找到其结果。
getMinIndexForSegment
如OP所述,如果数字仅包含正数,那么我们只需要比较int getMinIndexForSegment (int i, int j){
int st = j + 1;
int ed = n - 1;
int res = n;
while(st <= ed){
int mid = (st + ed)/2;
if(segment(i, j) < seg(j + 1, mid)){
res = mid;
ed = mid - 1;
}else{
st = mid + 1;
}
}
return res;
}
和(i , j)
和(j + 1 , k)
的两个段
答案 1 :(得分:1)
我们可以有一个O(n^2)
算法。令f(i, j, s)
代表直到段i
的第s
个字符并向后扩展j
个字符的段为止的有效分区数。然后:
f(i, j, s):
# A segment extending all the way to the start
if i + 1 == j:
return 1
# A one-character segment that's smaller
# than the preceding character
if j == 1 and s[i] <= s[i - 1]:
return 0
segment = s[i - j + 1...i]
# Find longest preceding segment in O(1)
longest =
a segment of length j extending back
from s[i - j] or length (j-1) if the first
segment was equal or larger than segment
# Replace 'sum' with O(1) prefix sum calculation
# since we can record that for each previous i
# as we increase j
return sum(f(i - j, k, s) for k = 1 to length(longest))