Algorithm 不同的子序列

Algorithm 不同的子序列,algorithm,dynamic-programming,Algorithm,Dynamic Programming,从 给定一个字符串S和一个字符串T,计算不同的 S中T的子序列 字符串的子序列是由 通过删除某些字符(可以是无字符)来创建原始字符串 不干扰其余字符的相对位置。 (即,“ACE”是“ABCDE”的子序列,而“AEC”不是) 下面是一个例子:S=“rabbit”,T=“rabbit” 返回3 我看到了一个非常好的DP解决方案,但是,我很难理解它,任何人都可以解释这个DP是如何工作的 int numDistinct(string S, string T) { vector<int&g

给定一个字符串S和一个字符串T,计算不同的 S中T的子序列

字符串的子序列是由 通过删除某些字符(可以是无字符)来创建原始字符串 不干扰其余字符的相对位置。 (即,“ACE”是“ABCDE”的子序列,而“AEC”不是)

下面是一个例子:S=“rabbit”,T=“rabbit”

返回3

我看到了一个非常好的DP解决方案,但是,我很难理解它,任何人都可以解释这个DP是如何工作的

int numDistinct(string S, string T) {

    vector<int> f(T.size()+1);

    //set the last size to 1.
    f[T.size()]=1;

    for(int i=S.size()-1; i>=0; --i){
        for(int j=0; j<T.size(); ++j){
            f[j]+=(S[i]==T[j])*f[j+1];
            printf("%d\t", f[j] );
        }
        cout<<"\n";
    }
    return f[0];
}
int numDistinct(字符串S,字符串T){
向量f(T.size()+1);
//将最后一个大小设置为1。
f[T.size()]=1;
对于(int i=S.size()-1;i>=0;--i){

对于(int j=0;j,首先,试着自己解决问题,想出一个简单的实现:

假设
s.length=m
T.length=n
。让我们为
s
的子串写
s{i}
,从
i
开始。例如,如果
s=“abcde”
s{0}=“abcde”
s{4}=“e
,和
s{5},我们对
使用类似的定义

N[i][j]
成为
S{i}
T{j}
的不同子序列。我们对
N[0][0]
感兴趣(因为它们都是完整的字符串)


有两个简单的例子:
N[i][N]
对于任何
i
N[m][j]
对于
j我认为答案很好,但有些地方可能不正确

我认为我们应该向后迭代
I
j
。然后我们将数组
N
更改为数组
f
,我们向前循环
j
以避免与最后得到的结果重叠

for (int i = m-1; i >= 0; i--) {
    for (int j = 0; j < n; j++) {
        if (S[i] == T[j]) {
            N[i][j] = N[i+1][j] + N[i+1][j+1];
        } else {
            N[i][j] = N[i+1][j];
        }
    }
}
用于(int i=m-1;i>=0;i--){
对于(int j=0;j
我不明白你的最后一句话。你能回顾一下你写的内容并确保它有意义吗?我错了二维数组编写的代码也是正确的,向前和向后的j都是正确的。但是当我们把二维数组改成一维数组时,我们必须向前循环j,我们不能在最后一个循环中得到结果(这里是j+1),最后一个循环的结果存储在数组f中,我们有“f[j]+=(S[i]==T[j])*f[j+1]”,我们向前循环j,所以我们确保在计算f[j]时f[j+1]没有被修改。@S.H。你可以把它看作是
(int i=0;如果这是一个愚蠢的问题,我很抱歉,但是dp如何确保只计算不同的子序列?@frodo每个子序列都是一个精确匹配的结果:一些
S
的字母与
T
的字母匹配,而另一些则不匹配。该算法循环遍历
S
的字母,并将输出相加当它与该字母匹配时,以及当它与
t
中的字母不匹配时,都会出现错误。没有第三个选项,因此不会重复计算。我希望这不会让您更加困惑;-)很好的解释!没有多少算法问题得到了回答,更不用说有如此高的质量了。我希望看到更多!
for (int i = m-1; i >= 0; i--) {
    for (int j = 0; j < n; j++) {
        if (S[i] == T[j]) {
            N[i][j] = N[i+1][j] + N[i+1][j+1];
        } else {
            N[i][j] = N[i+1][j];
        }
    }
}
f[j] = 0, for 0 <= j < n
f[n] = 1

for (int i = m-1; i >= 0; i--) {
    for (int j = 0; j < n; j++) {
        if (S[i] == T[j]) {
            f[j] = f[j] + f[j+1];
        } else {
            f[j] = f[j];
        }
    }
}
if (S[i] == T[j]) {
    f[j] += f[j+1];
}
f[j] += (S[i] == T[j]) * f[j+1];
f[n] = 1

for (int i = m-1; i >= 0; i--) {
    for (int j = 0; j < n; j++) {
        f[j] += (S[i] == T[j]) * f[j+1];
    }
}
for (int i = m-1; i >= 0; i--) {
    for (int j = 0; j < n; j++) {
        if (S[i] == T[j]) {
            N[i][j] = N[i+1][j] + N[i+1][j+1];
        } else {
            N[i][j] = N[i+1][j];
        }
    }
}