【问题标题】:Optimal string containing all strings from a given set as substrings包含来自给定集合的所有字符串作为子字符串的最佳字符串
【发布时间】:2012-05-04 09:14:35
【问题描述】:

我正在处理一些需要大型(恒定)位数组的代码。由于它包含较大的常量跨度(全为 0 或全为 1),因此我将其分解为一个允许省略重复跨度(常量或其他)的两级表,如下所示:

bitn = table2[table1[n/256]+n%256/8]&1<<n%8

此时,table1 的条目都是 32 的倍数(256 位),但我想知道是否可以通过允许 table2 中的跨度重叠来实现显着节省。所以我的问题是(以抽象形式陈述):

给定 N 个长度为 K 的字符串 { S_n : n=1..N },是否有一种有效的方法可以找到最短长度的字符串 S 使得每个 S_n 都是 S 的子字符串?

(请注意,由于我可能希望保持我的位数组 8 位对齐,我对问题的特定应用可能是处理 8 位字节的字符串而不是位的字符串,但是这个问题在任何情况下都是有意义的字符的意义——位、字节或其他。)

【问题讨论】:

  • 我怀疑这是 NP 难的,因为没有办法建立处理这些可能导致类似 DP 的解决方案的顺序,但我没有知识来证明它。您可能会在理论或数学溢出方面得到更好的答案

标签: c string algorithm optimization


【解决方案1】:

关于具有大段常量的大型常量位数组,这是设计表格供您考虑的另一种方法(我不知道您的确切需求,所以我不能说它是否有帮助或不是)。

考虑类似radix tree。为了方便解释,让我定义 get 函数:

#define TYP_CONST
#define TYP_ARRAY

struct node {
    unsigned min;
    unsigned max;
    int typ;
    union {
        char *bits;
        int constant;
    } d;
    struct node *left;
    struct node *right;
}

struct bit_array {
    unsigned length;
    struct node *root;
}

int get(struct bit_array *b, unsigned ix)
{
    struct node *n = b->root;
    if (ix >= b->length)
        return -1;
    while (n) {
        if (ix > n->max) {
            n = n->right;
            continue;
        } else if (ix < n->min) {
            n = n->left;
            continue;
        }
        if (n->typ == TYP_CONST)
            return n->d.constant;
        ix -= n->min;
        return !!(n->d.bits[ix/8] & (1 << ix%8));
    }
    return -1;
}

用人类的话来说,你想在树中搜索你的比特。每个节点负责一定范围的位,您可以在范围内进行二进制搜索以找到您想要的范围。

找到范围后,有两个选项:常量或数组。如果常量,只需返回常量(为您节省大量内存)。如果是数组,则在位数组中进行数组查找。

您将有 O(log n) 的查找时间而不是 O(1).... 尽管它仍然应该非常快。

这里的困难在于设置适当的数据结构很烦人且容易出错。但是你说数组是恒定的,所以这可能不是问题。

【讨论】:

    【解决方案2】:

    首先,这个问题可以表述为一个 TSP。我们有一组节点(每个字符串都是一个节点),我们需要找到访问所有节点的路径。字符串 x 和 y 之间的距离定义为 len(xy)+len(y) 其中 xy 是同时具有 x 和 y 且以 x 开头的最优字符串(例如 x=000111, y=011100, xy=0001100 , 距离(x,y) = 8-6=2)。

    请注意,这也符合三角不等式(distance(x,z)

    此版本的 TSP 称为 (1,B)-ATSP。此类问题的分析及近似解见http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.20.3439

    【讨论】:

    • 我不认为最佳重叠可以确定为仅两个字符串的函数。例如 000111 和 111000。我们可以使用 000111000 或 111000111。这将影响其他字符串如何被同化为更大的字符串
    • @spinning_plate 没错!这就是为什么它是非对称TSP。根据我的定义,xy 与 yx 不同。
    • 对,对不起,错过了那部分
    猜你喜欢
    • 2011-01-28
    • 2017-11-23
    • 1970-01-01
    • 1970-01-01
    • 2015-07-22
    • 2011-03-18
    • 2011-02-19
    • 2021-02-02
    相关资源
    最近更新 更多