Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 交错字符串的动态规划问题求解_Java_Algorithm - Fatal编程技术网

Java 交错字符串的动态规划问题求解

Java 交错字符串的动态规划问题求解,java,algorithm,Java,Algorithm,我试图解决这个问题,但我放弃了,找到了下面的解决方案,尽管我不明白这个解决方案是如何工作的,或者为什么工作。我们将非常感谢任何深入的解决办法 问题: 给定s1,s2,s3,找出s3是否由s1的交织形成 和s2 例如,假设: s1 = "aabcc" s2 = "dbbca" 当s3=“aadbbcac”时,返回true 当s3=“aadbbbaccc”时,返回false 解决方案: public static boolean isInterleave(String s1, String

我试图解决这个问题,但我放弃了,找到了下面的解决方案,尽管我不明白这个解决方案是如何工作的,或者为什么工作。我们将非常感谢任何深入的解决办法

问题:

给定
s1
s2
s3
,找出
s3
是否由
s1
的交织形成 和
s2

例如,假设:

s1 = "aabcc"
s2 = "dbbca"
  • s3=“aadbbcac”
    时,返回true
  • s3=“aadbbbaccc”
    时,返回false
解决方案:

  public static boolean isInterleave(String s1, String s2, String s3) {
        if (s3.length() == 0 && s1.length() == 0 && s2.length() == 0)
            return true;

        else if (s3.length() != s1.length() + s2.length())
            return false;
        boolean isInter[][] = new boolean[s1.length()+1][s2.length()+1];
        isInter[0][0] = true;
        for ( int i = 1; i <= s1.length(); ++i){
            if (s1.charAt(i-1) == s3.charAt(i-1))
                isInter[i][0] = true;
            else
                break;
        }
        for ( int i = 1; i <= s2.length(); ++i){
            if (s2.charAt(i-1) == s3.charAt(i-1))
                isInter[0][i] = true;
            else
                break;
        }
        // DP
        for ( int i = 1; i <= s1.length(); ++i){
            for ( int j = 1; j <= s2.length(); ++j){
                if (s3.charAt(i+j-1) == s1.charAt(i-1))
                    isInter[i][j] = isInter[i-1][j] || isInter[i][j];
                if (s3.charAt(i+j-1) == s2.charAt(j-1))
                    isInter[i][j] = isInter[i][j-1] || isInter[i][j];
            }
        }
        return isInter[s1.length()][s2.length()];
    }
public静态布尔ISinterleve(字符串s1、字符串s2、字符串s3){
如果(s3.length()==0&&s1.length()==0&&s2.length()==0)
返回true;
如果(s3.length()!=s1.length()+s2.length())
返回false;
布尔isInter[][]=新布尔值[s1.length()+1][s2.length()+1];
isInter[0][0]=真;

对于(int i=1;i我在这里使用Python切片语法,因为它很好。
S[:-1]
表示删除最后一个字符的字符串
S
S[:n]
表示长度
n
的前缀
S

关键思想是,如果
C
A
B
的交织,那么
C[:-1]
要么是
A
B[:-1]
的交织,要么是
A[:-1]的交织另一方面,如果
C
A
B
的交织,那么
C+'X'
A+'X'
B
的交织,也是
A
B+'X'
的交织

这些是我们应用动态规划所需的子结构属性

我们定义了
f(i,j)=true
,如果
s1[:i]
s2[:j]
可以交错形成
s3[:(i+j)]
f(i,j)=false,否则

f(0,0) = true
f(i,0) = f(i-1, 0) if s3[i-1] == s1[i-1]
f(0,j) = f(0, j-1) if s3[j-1] == s2[j-1]
f(i,j) = true if s3[i+j-1] = s1[i-1] and f(i-1, j)
f(i,j) = true if s3[i+j-1] = s2[j-1] and f(i, j-1)
在所有其他情况下,我们有
f(i,j)=false
。 Java代码只是使用动态编程实现了这个循环。也就是说,我将以更简洁的方式实现它:

for (int i = 0; i <= s1.length(); ++i)
    for (int j = 0; j <= s2.length(); ++j)
        isInter[i][j] = (i == 0 && j == 0)
           || (i > 0 && s1.charAt(i-1) == s3.charAt(i+j-1) && isInter[i-1][j])
           || (j > 0 && s2.charAt(j-1) == s3.charAt(i+j-1) && isInter[i][j-1]);
for(inti=0;i0和s2.charAt(j-1)==s3.charAt(i+j-1)和&isInter[i][j-1]);

前几行只处理简单的情况,这些情况只能根据输入字符串的长度来解决。这些测试通过允许假定长度匹配来简化剩余的代码

算法的核心是计算一个数组
isInter
,其中
isInter[i][j]
在迭代
(i,j)后为真
s1
的第一个
i
字符与
s2
的第一个
j
字符交错,可以形成
s3
的第一个
i
字符的当且仅当

isInter[i][0]
当且仅当
s3
的第一个
i
字符与
s1
的第一个
i
字符匹配时为真。类似地,
isInter[0][i]当且仅当
s3
的第一个
i
字符与
s2
的第一个
i
字符匹配时,
为真

最后一个循环使用已计算的元素以及
s3
的下一个字符与
s1
的下一个字符或
s2
的下一个字符之间的匹配来构建isInter的其余元素


完全计算完
isInter
后,
isInter[s1.length()][s2.length()]如果整个C++代码> S2与整个代码< > S2一起,则是真正的,如果整个和全部代码都可以形成“<代码> S3</代码>。

< P>这里是另一个尝试,说明代码是如何工作的,使用C++中的非常简单的语法。代码中有一些内联注释,您不能理解。

//使用动态编程:O(n^2)
布尔值是交错的(字符串s1、字符串s2、字符串s3)
{
bool-ret=假;
int len1=s1.length();
int len2=s2.length();
int len3=s3.length();
if(len1+len2!=len3)
{
返回ret;
}
#定义M(i,j)匹配[(i)*len1+(j)]
//bool匹配[len1+1][len2+1];//todo;使用动态分配
bool*match=新bool[(len1+1)*(len2+1)];
int i,j,k;
/*init match表全部为false*/

对于(i=0;我认为这揭示了代码中的一个错误--
if(s1.charAt(i-1)==s3.charAt(i-1))
应该是
if(s1.charAt(i-1)==s3.charAt(i-1)&&isInter[i-1][0])
,第二个基本情况循环也是如此。@j_random_hacker我认为
break
语句有效地实现了这一规则。isInter的所有元素最初都是
false
。啊,的确如此——错误在我身上!嗨,你能改变你的答案以支持Java吗?我不懂Python字符串转换语法。@Shahrukh安:如果需要,您可以自己翻译:正如我提到的,
A[:n]=A.substring(0,n)
A[:-1]=A.substring(0,A.length-1)
。我认为您遇到的主要问题是在概念层面上,因此伪代码应该可以帮助您理解我如何提高对DP问题的理解,介意分享一下您所做的事情,以便快速了解问题所在吗?请参考一些资源/书籍,以便我能够尽可能地了解问题所在you@ShahrukhKhanUnfor值得一提的是,没有一个技巧可以神奇地让你更快地解决问题。但是它有助于理解DP(最优子结构属性)背后的理论。它也有助于递归而不是迭代思考。在获得基本知识的情况下,思考问题(实践!)是最好的学习方式。有像TopCoder和Codeforces这样的平台,有大量的资料。实际上在学习基础知识方面有些有用(有一个
//using dynamic programming : O(n^2)
bool is_interleaved_On2_DP(string s1, string s2, string s3)
    {
    bool ret = false;
    int len1 = s1.length();
    int len2 = s2.length();
    int len3 = s3.length();

    if( len1 + len2 != len3 )
        {
        return ret;
        }

#define M(i, j) match[ (i) * len1 + (j) ]

    //bool match[len1 + 1][len2 + 1]; //todo; use dynamic allocation
    bool* match = new bool[ (len1+1)*(len2+1) ];
    int i, j, k;

    /* init match table to be all false */
    for( i = 0; i <= len1; i++ )
        {
        for( j = 0; j <= len2; j++ )
            {
            M(i, j) = false;
            }
        }

    /* init match[0][0] == true */
    M(0, 0) = true; //why ? null is interleaving 2 other nulls :)

    /* init the s1 side of table i.e. column */
    for( i = 1; i <= len1; i++ )
        {
        char c1 = s1[i - 1];
        char c3 = s3[i - 1];
        if(c1 == c3)
            {
            M(i, 0) = true;
            }
        else
            {
            break;
            }
        }

    /* init the s2 side of table i.e. row */
    for( j = 1; j <= len2; j++ )
        {
        char c2 = s2[j - 1];
        char c3 = s3[j - 1];
        if(c2 == c3)
            {
            M(0, j) = true;
            }
        else
            {
            break;
            }
        }

    /* compute remaining table */
    for( i = 1; i <= len1; i++ )
        {
        char c1 = s1[i - 1];
        for( j = 1; j <= len2; j++ )
            {
            char c2 = s2[j - 1];
            int k = i + j; //index for s3
            char c3 = s3[k - 1];

            if(c1 == c3)
                {
                M(i, j) = M(i - 1, j) || M(i, j);
                }

            if(c2 == c3)
                {
                M(i, j) = M(i, j - 1) || M(i, j);
                }
            }
        }

    ret = M(len1, len2);

    delete [] match;
#undef M
    return ret;
    }