简体   繁体   中英

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

I am trying to 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

I tried to use recursion.

// 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);
    }
}

The difference between snippet 1 and snippet 2 is that in snippet 2, I have appended the temp string with the character before passing it into the function. The second code gives result(string) whose size is greater than sum of length of both input strings.

Here's a version with plenty of cout and a way to track recursion depth.

#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;
}

which yields this output for 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

and this for 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

To help see the recursion look at the correct output when depth is 1 as the first level of a tree with 2 branches. They should be just the first characters of each string. Now each of those nodes get children for each remaining character. At the next lower level (depth 2), you add a character then each of those nodes gets children to create level/depth 3...etc. It builds a trie when done correctly and temp only changes length once at each depth.

In both, you bottom out and print when you reach a leaf.

In the incorrect version, you'll see that length of temp is inconsistent in a given depth of the recursion. As already said but in a different way, appending to temp and storing it locally (which can also be thought of as appending while still in a row/level/depth of the trie) causes length of temp to grow both left to right and top to bottom.

I think you should use std::next_permutation(). For the first string, add for each character a 0 to a vector. Do the same for the second string with a 1. Now you have one vector to permutate. For each permutation, simply remap the indices back to the next character in first string if it is even and second when odd.

Example permutation : "cat", "bird" to (0 0 0 1 1 1 1), one permutation becomes (0 1 1 0 1 0 1 ) which you can remap to "cbiartd"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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