String 返回在两个给定字符串之间排序的新字符串

String 返回在两个给定字符串之间排序的新字符串,string,algorithm,sorting,String,Algorithm,Sorting,给定两个字符串a和b,其中a在字典上abcf abc~abchi->abc+\uh->abc 连续字符 如果两个不同的字符按字典顺序连续,请首先复制左字符,然后在左字符串的下一个字符和字母表末尾之间添加字符: abhs~abit->ab+h~i->abh+s~(->abhw abh~abit->ab+h~i->abh+~\uUh->abhn 如果左字符串中的下一个字符是一个或多个z,则复制它们并在第一个非z字符和字母表末尾之间添加字符: abhz~abit->ab+h~i->abh+z~┱-

给定两个字符串a和b,其中a在字典上
有一个实用的算法吗?

这是一个非常简单的方法来实现这一点,可能远远不是最优的(当然取决于你所说的最优)

我只使用
a
b
。我想你可以用更多的字母来概括这一点

两个简单的观察结果:

  • 在另一个字符串后面创建一个新字符串很容易:只需附加一个或多个字母。例如,
    abba
    <
    abba
  • 只有当
    x
    b
    结尾时,才能保证在另一个字符串
    x
    之前创建一个新字符串。现在,用
    a
    替换
    b
    ,并附加一个或多个字母。例如,
    abbab
    abbaab

  • 算法现在非常简单。以
    a
    b
    作为哨兵开始。在两个现有钥匙
    x
    y
    之间插入新钥匙:

    • 如果
      x
      y
      的前缀:新键是
      y
      ,其结尾
      b
      替换为
      ab
    • 如果
      x
      不是
      y
      的前缀:新键是
      x
      ,附加了
      b

    运行示例:

    a, b
    a, ab*, b
    a, aab*, ab, b
    a, aab, ab, abb*, b
    a, aab, ab, abab*, abb, b
    a, aaab*, aab, ab, abab, abb, b
    

    最小化字符串长度

    如果希望将字符串长度保持在最小值,可以创建一个在左右字符串之间按字典顺序排列的字符串,以便有空间插入其他字符串,并且仅在绝对必要时创建更长的字符串

    我将假设字母表[a-z]和字典顺序,其中空格位于“a”之前,因此例如“ab”位于“abc”之前

    基本情况

    首先从字符串的开头复制字符,直到遇到第一个差异(可能是两个不同的字符,也可能是左字符串的结尾):

    abcde~abchi->abc+d~h
    abc~abchi->abc+\uh
    
    然后,通过在字母表中左字符(或字母表的开头)和右字符之间的中间添加字符来创建新字符串:

    abcde~abchi->abc+d~h->abcf
    abc~abchi->abc+\uh->abc
    
    连续字符

    如果两个不同的字符按字典顺序连续,请首先复制左字符,然后在左字符串的下一个字符和字母表末尾之间添加字符:

    abhs~abit->ab+h~i->abh+s~(->abhw
    abh~abit->ab+h~i->abh+~\uUh->abhn
    
    如果左字符串中的下一个字符是一个或多个z,则复制它们并在第一个非z字符和字母表末尾之间添加字符:

    abhz~abit->ab+h~i->abh+z~┱->abhz+┱~┱->abhzn
    abhzs~abit->ab+h~i->abh+z~ u->abhz+s~ u->abhzw
    abhzz~abit->ab+h~i->abh+z~->…->abhzz+u~ uz->abhzzn
    
    右边的字符是a或b

    永远不要在左字符串后面加上“a”来创建字符串,因为这样会创建两个按字典顺序连续的字符串,在这两个字符串之间不能再添加其他字符串。解决方案是始终在字母表开头和右字符串中的下一个字符之间添加一个附加字符:

    abc~abcah->abc+\ua->abca+\uh->abcad
    abc~abcab->abc+\ua->abca+\ub->abcaa+\uu->abcaan
    abc~abcaah->abc+\uA->abca+\uA->abcaa+\uH->abcaad
    abc~abcb->abc+\ub->abca+\uuu->abcan
    
    代码示例

    下面是演示该方法的代码片段。这有点复杂,因为JavaScript,但实际上并不复杂。要生成第一个字符串,请使用两个空字符串调用函数;这将生成字符串“n”。要在最左边的字符串之前或最右边的字符串之后插入字符串,请使用该字符串和空字符串调用函数

    功能中间串(上一个,下一个){
    变量p,n,pos,str;
    对于(pos=0;p==n;pos++){//查找最左边的不匹配字符
    p=pos"strings": [
      "n",
      "u",
      "x",
      "z",
      "zn",
      "zu",
      "zx",
      "zz",
      "zzn",
      "zzu",
      "zzx",
      "zzz",
      "zzzn",
      "zzzu",
      "zzzx",
      "zzzz",
      "...etc...",
      "zzzzzzzzzzzzzzzzzzzzzzzzn",
      "zzzzzzzzzzzzzzzzzzzzzzzzu",
      "zzzzzzzzzzzzzzzzzzzzzzzzx",
      "zzzzzzzzzzzzzzzzzzzzzzzzz",
      "zzzzzzzzzzzzzzzzzzzzzzzzzn"
    ]
    
    // Copyright 2021 Google LLC.
    // SPDX-License-Identifier: Apache-2.0
    template <typename Str, typename Digit>
    Str midpoint(const Str left, const Str right, Digit zero, Digit nine) {
      Str mid;
      for (auto i = left.size() - left.size();; ++i) {
        Digit l = i < left.size() ? left[i] : zero;
        Digit r = i < right.size() ? right[i] : nine;
        if (i == right.size() - 1) --r;
        // This is mid += (l + r + 1)/2
        // without needing Digit to be wider than nine.
        r -= l;
        mid += l + r/2 + (r&1);
        if (mid.back() != l) break;
      }
      return mid;
    }