繁体   English   中英

查找可以由保留字符串顺序的第一和第二个字符串的所有字符组成的给定字符串的所有交织

[英]Find all interleavings of given strings that can be formed from all the characters of first and second string where order of characters is preserved

我试图找到可以由保留字符串顺序的第一和第二字符串的所有字符组成的给定字符串的所有交织

我试图使用递归。

// This code works[Snippet 1]
void func(string str1,string str2,string temp){

    if(!str1.length() && !str2.length()){
        cout << temp << endl;
        return;
    }

    if(str1.length()){
        func(str1.substr(1),str2,temp+str1[0]);
    }

    if(str2.length()){
        func(str1,str2.substr(1),temp+str2[0]);
    }
}

// This code does not work[Snippet 2]
void func(string str1,string str2,string temp){

    if(!str1.length() && !str2.length()){
        cout << temp << endl;
        return;
    }

    if(str1.length()){
        temp+=str1[0];
        func(str1.substr(1),str2,temp);
    }

    if(str2.length()){
        temp+=str2[0];
        func(str1,str2.substr(1),temp);
    }
}

片段1和片段2之间的区别在于,在片段2中,我在将temp字符串附加到该字符之前,将其传递给函数。 第二个代码给出result(string),其大小大于两个输入字符串的长度之和。

下面是用大量的版本cout和方法来跟踪递归深度。

#include <iostream>
#include <string>

using namespace std;

void func0(string str1, string str2, string temp, int depth) {

    if (!str1.length() && !str2.length()) {
        cout << temp << endl;
        depth--;
        return;
    }

    if (str1.length()) {
        cout << "depth: " << depth++ << "|temp: " << temp << '\n';
        func0(str1.substr(1), str2, temp + str1[0], depth);
    }

    if (str2.length()) {
        cout << "depth: " << depth++ << "|temp: " << temp << '\n';
        func0(str1, str2.substr(1), temp + str2[0], depth);
    }

    depth--;
}

void func1(string str1, string str2, string temp, int depth) {
    if (!str1.length() && !str2.length()) {
        cout << temp << endl;
        depth--;
        return;
    }

    if (str1.length()) {
        temp += str1[0]; //temp has
        cout << "depth: " << depth++ << "|temp: " << temp << '\n';
        func1(str1.substr(1), str2, temp, depth);
    }

    if (str2.length()) {
        temp += str2[0];
        cout << "depth: " << depth++ << "|temp: " << temp << '\n';
        func1(str1, str2.substr(1), temp, depth);
    }

    depth--;
}

int main(int argc, char* argv[]) {
    string a = "asd";
    string b = "qw";
    string c = "";

    cout << "func0\n";
    func0(a, b, c, 0);
    cout << "func1\n";
    func1(a, b, c, 0);

    return 0;
}

这将为func0产生以下输出:

func0
depth: 0|temp:
depth: 1|temp: a
depth: 2|temp: as
depth: 3|temp: asd
depth: 4|temp: asdq
asdqw
depth: 3|temp: as
depth: 4|temp: asq
depth: 5|temp: asqd
asqdw
depth: 5|temp: asq
depth: 6|temp: asqw
asqwd
depth: 2|temp: a
depth: 3|temp: aq
depth: 4|temp: aqs
depth: 5|temp: aqsd
aqsdw
depth: 5|temp: aqs
depth: 6|temp: aqsw
aqswd
depth: 4|temp: aq
depth: 5|temp: aqw
depth: 6|temp: aqws
aqwsd
depth: 1|temp:
depth: 2|temp: q
depth: 3|temp: qa
depth: 4|temp: qas
depth: 5|temp: qasd
qasdw
depth: 5|temp: qas
depth: 6|temp: qasw
qaswd
depth: 4|temp: qa
depth: 5|temp: qaw
depth: 6|temp: qaws
qawsd
depth: 3|temp: q
depth: 4|temp: qw
depth: 5|temp: qwa
depth: 6|temp: qwas
qwasd

而对于func1:

func1
depth: 0|temp: a
depth: 1|temp: as
depth: 2|temp: asd
depth: 3|temp: asdq
depth: 4|temp: asdqw
asdqw
depth: 3|temp: asdq
depth: 4|temp: asdqd
depth: 5|temp: asdqdw
asdqdw
depth: 5|temp: asdqdw
depth: 6|temp: asdqdwd
asdqdwd
depth: 2|temp: asq
depth: 3|temp: asqs
depth: 4|temp: asqsd
depth: 5|temp: asqsdw
asqsdw
depth: 5|temp: asqsdw
depth: 6|temp: asqsdwd
asqsdwd
depth: 4|temp: asqsw
depth: 5|temp: asqsws
depth: 6|temp: asqswsd
asqswsd
depth: 1|temp: aq
depth: 2|temp: aqa
depth: 3|temp: aqas
depth: 4|temp: aqasd
depth: 5|temp: aqasdw
aqasdw
depth: 5|temp: aqasdw
depth: 6|temp: aqasdwd
aqasdwd
depth: 4|temp: aqasw
depth: 5|temp: aqasws
depth: 6|temp: aqaswsd
aqaswsd
depth: 3|temp: aqaw
depth: 4|temp: aqawa
depth: 5|temp: aqawas
depth: 6|temp: aqawasd
aqawasd

为了帮助您查看递归,请在深度为1时将正确的输出视为具有2个分支的树的第一级。 它们应该只是每个字符串的第一个字符。 现在,这些节点中的每个节点都会为每个剩余字符获得子级。 在下一个较低的级别(深度2),您添加一个字符,然后每个节点都将使子节点创建级别/深度3 ...等。 正确完成后,它会建立一个特例,并且temp在每个深度仅更改一次长度。

在这两种方法中,您都将触底并在到达叶子时进行打印。

在不正确的版本中,您将看到在给定的递归深度中temp长度不一致。 如前所述,但以不同的方式,将temp附加并存储在本地(也可以将其视为仍在特里的行/级别/深度中附加)会导致temp长度从左到右和从顶部增加到底部。

我认为您应该使用std :: next_permutation()。 对于第一个字符串,为每个字符向向量添加0。 使用1对第二个字符串执行相同的操作。现在,您可以对一个向量进行排列。 对于每个排列,只需将索引重新映射回第一个字符串中的下一个字符(如果它为偶数),第二个就为奇数。

排列示例:“ cat”,“ bird”到(0 0 0 1 1 1 1 1),一个排列变成(0 1 1 0 1 0 1),您可以将其重新映射到“ cbiartd”

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM