给定一些单词,找到一个序列,使得该序列的任何相邻单词不能具有相同的字符

发布于 2024-12-25 10:49:46 字数 307 浏览 3 评论 0原文

给出一些话, 例如 banana、cat、dog、elephant、type、middle、lake

找到一个序列,使得

(1) 每个单词都在序列上

(2) 任何相邻单词不能具有相同的字符。

如果找不到 seq,则返回 false。否则,返回 true 和 seq。

无重复。没有单词的排列。

我的想法:

建立一个图,并使用哈密顿路径来找到序列。

但是,它是一个NP完全的。

如何避免哈密顿路径?

还有更好的想法吗?

谢谢

Given some words,
e.g.
banana , cat , dog, elephant, type, middle, lake

find a sequence such that

(1) every word is on the sequence

(2) any adjacent words cannot have same characters.

If the seq cannot be found, return false. otherwise, return true and the seq.

No duplicated. No permutations of words.

My idea:

Set up a graph, and use Hamiltonian path to find the seq.

But, it is a NP complete.

How to avoid Hamiltonian path ?

Any better ideas ?

thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

绅刃 2025-01-01 10:49:46

请注意,如果您构建了部分序列,则只有最后一个单词才能确定您可以使用哪些其他单词来继续该序列。例如,如果您选择了“香蕉”和“狗”,则可以继续选择“类型”或“湖”(“湖”与“香蕉”碰撞并不重要,因为“湖”将与“湖”相邻) “狗”)。由于您必须按照单词出现的顺序使用单词(如果我正确理解您的描述),您可以使用 动态编程 来解决“我能生成的以第 i 个单词结尾的最长单词序列是什么?”的问题。

Note that if you have constructed a partial sequence, it is only the last word that determines which other words you may continue the sequence with. For instance, if you have selected "banana" and "dog", you may continue with "type" or "lake" (it doesn't matter that "lake" collides with "banana", because "lake" will be adjacent to "dog"). Since you must use the words in the order they appear (if I understand your description correctly), you can use dynamic programming to solve the problem "what is the longest sequence of words I can produce that ends with the i th word?"

森末i 2025-01-01 10:49:46

我的方法将涉及一个结构:

struct node{
    char c1, c2;
    char* str;
    int used;
    int ind;
    std::vector<struct node*> valid;
};

c1 将是 str 中的第一个字符,c2 将是最后一个。我将循环输入数组并为每个项目生成一个节点,并可能将它们放入 std::vector 中。然后在每个节点上,push_back() 对可以有效放置在该节点前面的所有节点的引用有效。然后我会递归地寻找路径。只需从第一个节点开始,标记它使用的,导航到有效的第一个索引,重复该节点,然后当控制返回到该点时,转到有效的下一个节点,执行相同的操作,然后从这里返回时,重置所有节点中使用的值。如果未找到匹配项,则返回 false。

这是一些代码。它确保每个单词的第一个和最后一个字母不匹配。修改限定表达式以满足您的需要。

#include<stdio.h>
#include<string.h>
#include<vector>

struct node{
    char c1, c2;
    char* str;
    int used;
    int ind;
    std::vector<struct node*> valid;
};

int ispath_rec( std::vector<node*> &nodes, int depth, int* returnarray );

int ispath( char** value, int valuec, int* returnarray ){
    std::vector<node*> nodes;
    for( int i = 0; i < valuec; i ++ ){
        node* a = new node;
        nodes.push_back(a);
        a->used = 0;
        a->str = value[i];
        a->c1 = value[i][0];
        a->c2 = value[i][strlen(value[i])-1];
        a->ind = i;
    }
    for( int i = 0; i < valuec; i ++ ){
        node* a = nodes[i];
        for( int j = 0; j < valuec; j ++ ){
            node* b = nodes[j];
            if( b->c1 != a->c2 && b != a ) /*b->c1 != a->c2 is the qualifying expression*/
                a->valid.push_back( b );
        }
    }
    return ispath_rec( nodes, valuec, returnarray );
}

int ispath_rec( std::vector<struct node*> &nodes, int depth, int* returnarray ){
    if( depth <= 0 )
        return 1;
    for( int i = 0; i < nodes.size(); i ++ ){
        if( nodes[i]->used == 0 ){
            nodes[i]->used = 1;
            *returnarray = nodes[i]->ind;
            if( ispath_rec( nodes[i]->valid, depth-1, returnarray + 1 ) == 1 )
                return 1;
            nodes[i]->used = 0;
        }
    }
    return 0;
}

int main(){
    char* tmp[] = {"hello","oeyh","aol", "loks", "sol"};
    int rets[5];
    if( ispath( tmp, 5, rets ) ){
        for( int i = 0; i < 5; i ++ ){
            printf(" %s ", tmp[rets[i]] );
        }
    }
}

My approach would involve a struct:

struct node{
    char c1, c2;
    char* str;
    int used;
    int ind;
    std::vector<struct node*> valid;
};

c1 would be the first character in str, and c2 would be the last. I would loop over the input array and generate a node for each item, and probably put them into a std::vector. Then on each node, push_back() a reference to all the nodes that could be validly placed in front of that node in to valid. Then I would recursively look for the path. Just start with the first node, label it used, navigate to the first index of valid, repeat for that node, then when control returns to that point, go to the next node in valid, do the same, then when returning from here, reset the used value in all the nodes. If a match isn't found, return false.

Here's a bit of code. It makes sure that the first and last letter of each word do not match. Modify the qualifying expression to suit your needs.

#include<stdio.h>
#include<string.h>
#include<vector>

struct node{
    char c1, c2;
    char* str;
    int used;
    int ind;
    std::vector<struct node*> valid;
};

int ispath_rec( std::vector<node*> &nodes, int depth, int* returnarray );

int ispath( char** value, int valuec, int* returnarray ){
    std::vector<node*> nodes;
    for( int i = 0; i < valuec; i ++ ){
        node* a = new node;
        nodes.push_back(a);
        a->used = 0;
        a->str = value[i];
        a->c1 = value[i][0];
        a->c2 = value[i][strlen(value[i])-1];
        a->ind = i;
    }
    for( int i = 0; i < valuec; i ++ ){
        node* a = nodes[i];
        for( int j = 0; j < valuec; j ++ ){
            node* b = nodes[j];
            if( b->c1 != a->c2 && b != a ) /*b->c1 != a->c2 is the qualifying expression*/
                a->valid.push_back( b );
        }
    }
    return ispath_rec( nodes, valuec, returnarray );
}

int ispath_rec( std::vector<struct node*> &nodes, int depth, int* returnarray ){
    if( depth <= 0 )
        return 1;
    for( int i = 0; i < nodes.size(); i ++ ){
        if( nodes[i]->used == 0 ){
            nodes[i]->used = 1;
            *returnarray = nodes[i]->ind;
            if( ispath_rec( nodes[i]->valid, depth-1, returnarray + 1 ) == 1 )
                return 1;
            nodes[i]->used = 0;
        }
    }
    return 0;
}

int main(){
    char* tmp[] = {"hello","oeyh","aol", "loks", "sol"};
    int rets[5];
    if( ispath( tmp, 5, rets ) ){
        for( int i = 0; i < 5; i ++ ){
            printf(" %s ", tmp[rets[i]] );
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文