【问题标题】:Minimum Lexicographic Rotation Using Suffix Array使用后缀数组的最小字典旋转
【发布时间】:2013-09-15 04:57:38
【问题描述】:
    Consider a string of length n (1 <= n <= 100000). 
    Determine its minimum lexicographic rotation. 
    For example, the rotations of the string “alabala” are:

    alabala

    labalaa

    abalaal

    balaala

    alaalab

    laalaba

    aalabal

    and the smallest among them is “aalabal”.

这是来自 ACM ICPC 2003 的问题。其他用户已经在堆栈流中询问过这个问题。[但这没有用,我想通过后缀 Array 来解决。]

如何使用 Suffix Array 解决这个问题?

到现在为止我做了什么??

(1) 假设给定的字符串是 S。

我将字符串 S 与自身连接得到字符串 S'。

即。 S'=S+S。

(2).然后我在O(nlog n )时间内找到了S'的后缀数组。

For example:
    S=alabala
    S'=alabalaalabala

Suffix No. Index    Suffixes

0       13      a
1       6       aalabala
2       9       abala
3       2       abalaalabala
4       11      ala
5       4       alaalabala
6       7       alabala
7       0       alabalaalabala
8       10      bala
9       3       balaalabala
10      12      la
11      5       laalabala
12      8       labala
13      1       labalaalabala

所以我算好后缀数组SA,SA[]={13,6,9,2,11,4,7,0,10,3,12,5,8,1}。

我还计算了每个后缀的 LCPs b/w [虽然我不确定我是否会在这个问题中需要它]。

现在如何进一步进行。如何使用 SA 来获得想要的结果?

用一个非常*小的例子来解释会非常有效

谢谢!!

【问题讨论】:

  • 在这种情况下只需获取小于 S 大小的第一个数字 6。

标签: algorithm suffix-array


【解决方案1】:

看来你应该在 SA 中取第一个后缀,索引在 0 和 length(S) - 1 之间。

一些解释:S 的所有旋转都在 S' 后缀的开头,从 0 到 length(S) - 1 之间的位置。后缀数组保持后缀按字典顺序排列,所以你只需要选择第一个从S的旋转。

【讨论】:

  • 这个解决方案是错误的!例如对于字符串 CABA,最小的后缀是 A 并加上单词的其余部分来完成旋转我们得到 ACAB,但最小的字典旋转是 ABAC!
  • 前面的评论不正确,答案几乎是正确的,前提是创建一个附加到自身的文本的后缀数组,并且仅从后缀中获取第一个长度(S)个字符。问题中 0
【解决方案2】:

如果您使用 O(n log n) 算法(按第一个字母排序,然后按前两个字母排序,然后按前四个字母排序,...),您可以稍微修改后缀数组。

不要对字符串的后缀进行排序,但它是循环旋转。它应该是算法中的非常小的修改。 A 然后你会直接得到想要的结果。

如果你仍然想使用你的方法,那么只需取第一个索引,它在 0 和 N 之间。

【讨论】:

    【解决方案3】:

    谢谢大家。vkorchagin 和 usamec 的答案对于大多数测试用例都是正确的,但它们不适用于以下测试用例(S="baabaa")

    S=baabaa; S'=baabaabaabaa;

    Suffix| Suffix  |  Suffixes
    Index | Length  |
    
    11      1       a
    10      2       aa
    7       5       aabaa
    4       8       aabaabaa
    1       11      aabaabaabaa
    8       4       abaa
    5       7       abaabaa
    2       10      abaabaabaa
    9       3       baa
    6       6       baabaa
    3       9       baabaabaa
    0       12      baabaabaabaa
    

    取第一个索引在 0 到 S.length()-1 之间的后缀 不适用于上述测试用例。如果我这样做,则结果为 4,但正确答案是 1。

    所以我修改了一下答案。

    这就是我对上述答案所做的或添加/修改的额外条件::

    (1)我取了索引在 0 到 S.length()-1 之间的第一个后缀。

    假设它的索引是 :=ExpectedIdx。

    在上述示例中,ExpectedIdx=4。

    (2).现在 ExpectedIdx 可能是也可能不是答案。原因是 Suffix Array 中的 Next suffix 可能会产生相同的答案。

    示例 ::

    取起始Index为4的后缀(ExpectedIdx)aabaabaa.,我们得到aabaab作为最小字典旋转字符串。

    取下一个后缀,aabaabaabaa。

    我们还得到 aabaab 作为最小 Lexograhic 旋转字符串。

    但前者需要移位 4,而后者需要移位 1。所以正确答案是 1,而不是 4。

    所以我使用了最长公共前缀(LCP)的概念来检查相似性并最终被接受。http://livearchive.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=756

    编辑:: 这是伪代码 -

    int ExpectedIdx,ExpectedSuffixNumber,ExpectedSuffixLength;
    for(int i=0;i<strlen(str);++i)//str = Length of S'
    {
        suffixsize=strlen(str)-SA[i];
        if(suffixsize>(Len/2))//Len/2:=Size of S
        {
            ExpectedIdx=SA[i];
            ExpectedSuffixNumber=i;
            ExpectedSuffixLength=suffixsize;
            break;
        }
    }
    //Now this ExpectediDx may or may not be the correct answer.
    
    int finalans=ExpectedIdx;//Lets assume initially that ExpectedIdx is a correct/final answer.
    for(int i=(ExpectedSuffixNumber+1);i<Len;++i)//Check the Next Suffix 
    {
        if(LCP[i]>Len/2)//LCP[i]=Lingest common prefix of adjacent prefixes in a suffix Array.
        {
            if(SA[i]>finalans)
            {
                finalans=SA[i];
            }
        }
        else
            break;
    }
    

    【讨论】:

    • 您是否在“确定最小词典旋转,如果有更多则选择旋转最小的那个”这个问题中说过?不,无论如何你不需要 LCP。您只需要在结束标记之前使用普通字符(因此“aa”出现在“a”之前,依此类推)。
    • @usamec:: 哦,是的,该死,我没有提到有问题的条件..对不起,无论如何,答案对我有用,我自己在你的答案中添加了一个额外的条件让我的答案被接受.... .
    猜你喜欢
    • 1970-01-01
    • 2013-02-06
    • 1970-01-01
    • 2012-04-06
    • 2020-04-28
    • 2021-01-29
    • 2014-10-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多