Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 确定一个字符串在O(n)时间内与原始字符串匹配的旋转次数?_Performance_Algorithm_Rotation - Fatal编程技术网

Performance 确定一个字符串在O(n)时间内与原始字符串匹配的旋转次数?

Performance 确定一个字符串在O(n)时间内与原始字符串匹配的旋转次数?,performance,algorithm,rotation,Performance,Algorithm,Rotation,有很多问题在讨论旋转字符串的最快/最佳方法,或者确定一个字符串是否是另一个字符串的旋转 例如,忽略输入的清理,您将看到IsRotation: public static bool IsRotation(string s1, string s2) { return (s1.Length == s2.Length && (s1 + s1).IndexOf(s2) != -1); } 对于Rotate,类似这样的内容: public static string Rotate(

有很多问题在讨论旋转字符串的最快/最佳方法,或者确定一个字符串是否是另一个字符串的旋转

例如,忽略输入的清理,您将看到IsRotation:

public static bool IsRotation(string s1, string s2)
{
    return (s1.Length == s2.Length && (s1 + s1).IndexOf(s2) != -1);
}
对于Rotate,类似这样的内容:

public static string Rotate(string s, int index)
{
    //Can't rotate.  Return input.
    if (s.Length < 2)
    {
        return s;
    }

    // Break input in half at rotation index
    var s1 = s.Substring(0, index);
    var s2 = s.Substring(index);

    // Reverse the halves
    var s1Reversed = Reverse(s1);
    var s2Reversed = Reverse(s2);

    // Join the reversed halves
    var joined = s1Reversed + s2Reversed;

    //Reverse and return the result.
    var rotated = Reverse(joined);
    return rotated;
}
我被告知有一个解决方案将在O(n)时间内运行。初学者解决方案如下所示:

public static int IdenticalRotationCount(this string s)
{
    //If length of s is less than two, we cannot rotate.  Return 1.
    if (s.Length < 2)
    {
        return 1;
    }

    //Get first char in s
    var first = s[0];

    //Consider input as first rotation that matches
    var count = 1;

    //Try each rotate position
    for (var i = 1; i < s.Length; ++i)
    {
        var c = s[i];

        //If current character doesn't start with same character as input
        //we can skip the rotation
        if (c != first)
        {
            continue;
        }

        //If the rotation at index i equals the input string, add 1 to result
        if (StringExtensions.Rotate(s, i) == s)
        {
            ++count;
        }
    }

    return count;
}
public static int IdenticalRotationCount(此字符串为s)
{
//如果s的长度小于2,则无法旋转。返回1。
如果(s.长度<2)
{
返回1;
}
//获取s中的第一个字符
var first=s[0];
//将输入视为匹配的第一个旋转
var计数=1;
//尝试每个旋转位置
对于(变量i=1;i
然而,如果你选择一个荒谬的输入,比如连续20万个“a”,它将运行相当长的一段时间

谁能提供一个在O(n)时间内运行的解决方案?我可以通过在旋转前将输入分成两半进行实际比较来看到N^2,而不是进行实际旋转,但看不到如何进行O(N)

谢谢


PS-如果有更合适的方式发布此类问题,请在评论中说明。我很乐意移动它。

我突然想到了这一点——想想这个问题:“如果我将原始字符串与自身连接起来,那么连接结果中原始字符串的第一个索引是什么”。稍加思考,我觉得它似乎能回答O(n)这个问题

例如。 原始字符串“ByeBye” 连接字符串“ByeByeByeBye”


原始字符串出现在连接字符串中的(基于0的)索引2处。这告诉你一些事情。

如果字符串等于其自身在偏移量
k
处的旋转,并且偏移量不小于此值,那么字符串必须是其长度
k
前缀的重复。然后,它也将等于它在
k
的所有倍数下的旋转,因此将精确地出现
n/k
这样的旋转,其中
n
是字符串的长度。这很容易证明


确实有一种
O(n)
算法来确定
k
。一种方法是使用Duval的Lyndon分解算法(参见)。这只是一个暗示;如果需要,我将看看是否可以生成一些实际的伪代码。

假设字符串是
n
a
s,后跟一个
b
(因此每个旋转都是唯一的)。
i
th测试将在位置
n-i
处失败,因此字符比较总数将为
O(n^2)
@rici-true,这低估了确定串联中原始位置的成本。D'oh.IdenticalRotationCount(“StackOverflow”)不应该=1吗?因为每个字符串都是itself@faisal-嗯,不一定。但足够公平;我应该说明的。
public static int IdenticalRotationCount(this string s)
{
    //If length of s is less than two, we cannot rotate.  Return 1.
    if (s.Length < 2)
    {
        return 1;
    }

    //Get first char in s
    var first = s[0];

    //Consider input as first rotation that matches
    var count = 1;

    //Try each rotate position
    for (var i = 1; i < s.Length; ++i)
    {
        var c = s[i];

        //If current character doesn't start with same character as input
        //we can skip the rotation
        if (c != first)
        {
            continue;
        }

        //If the rotation at index i equals the input string, add 1 to result
        if (StringExtensions.Rotate(s, i) == s)
        {
            ++count;
        }
    }

    return count;
}