Algorithm 简单算法分析

Algorithm 简单算法分析,algorithm,complexity-theory,analysis,Algorithm,Complexity Theory,Analysis,我正在尝试将算法的复杂度降低到至少O(n^(3/2))。以下是算法: function( string s, int n ) { bool result = false; int position = 0; for( int i = 0; i < n/2; i++ ) { position = 0; for( int j = i+1; j < n; j++ ) { if( s[j]

我正在尝试将算法的复杂度降低到至少O(n^(3/2))。以下是算法:

function( string s, int n )
{
    bool result = false;
    int position = 0;
    for( int i = 0; i < n/2; i++ )
    {
        position = 0;
        for( int j = i+1; j < n; j++ )
        {
            if( s[j] != s[position] ) break;        
            if( j == n ) result = true;
            if( position == i ) position = 0;
            else position++;        
        }
        if(result) break;       
    }
    return result;
}
函数(字符串s,int n)
{
布尔结果=假;
int位置=0;
对于(int i=0;i
第一个for循环将迭代n/2次,这是O(n)复杂度。我需要使for循环的内部最大为O(sqrt(n)),从而使整个算法的复杂度为O(n^(3/2))。我很难确定嵌套for循环是否是我所需要的正确复杂性

注意:
n
是字符串的大小。该函数主要检查字符串s中是否出现重复模式。s中唯一的字符是
“0”
“1”
。例如,如果字符串为
“001001”
,则模式为
“001”
,并出现两次。绳子也是平的。也就是说,语法和功能与这个问题无关。所有的基本动作都被认为是O(1)(常数)时间,这几乎是这段代码的全部

注2:
我这样做是为了做作业。但是家庭作业的问题只是让算法工作,我已经做了。降低复杂性只是额外的练习工作


任何帮助或指导都将不胜感激

我认为您的内部循环不能降到O(sqrt(n)),因为您必须将字符串开头的所有字符与值由外部循环控制的特定索引I中的字符进行比较

这很简单,只需检查长度是否除以总长度(必须检查,如果L不除以总长度,则字符串不能是长度L的重复模式),如果不除以总长度,则不要运行内部循环。。。除数的上界是2sqrt(n),所以这保证了O(Nsqrt(n))

如果你想知道为什么,一个数字可能拥有的最大除数数是每一个sqrt(n)以下的数字,然后对于这些数字中的每一个x,n/x。所以在2sqrt(N)下

当然,在现实中,数字的除数要少得多,除了12,它实际上有所有的除数:1,2,3(每个数字到sqrt),12/1,12/2,12/3(倒数)

有两个内部循环,但一个运行L次,另一个运行N/L次,因此内部循环为O(N)

否则它将是O(N^2)


虽然外环乍一看似乎是N/2,但从数学上讲,它保证<2sqrt(N)。通过在几百万个字符的字符串上运行它,您也可以看到这一点,它将很快工作。

算法的作用是什么?我在代码下的“注意:”中解释了这一点。它确定字符串s是否由重复模式组成。例如,“001001”由两个“001”组成。“000000”由“0”构成6次。“010100”将是一个不由模式组成的示例。这是一个O(N)作业。你需要一个稍微修改一下的字符串搜索算法。我是说,一个O(N)字符串搜索算法,比如Knuth Morris Pratt。@svinja:这叫做“查找字符串的周期”。一种简单的方法是在一个正方形内搜索字符串(第一个和最后一个字符被切掉,以消除不重要的情况)。有一个(pdf)讨论了平均运行时间更好的算法。它说整个算法可以在O(n^3/2)复杂度下完成。我认为外部循环必须是O(n),然后是内部循环(sqrt(n)),这就是我设计它的方式。它应该被翻转吗?哦,这很有道理。我对自己的内部循环有多复杂感到困惑。非常感谢,这澄清了一些事情!
    static bool f(string s)
    {
        int n = s.Length;
        for (int l = n / 2; l >= 1; l--)
        {
            if (n % l != 0) continue;
            bool d = true;
            for (int o = 0; o < l; o++)
            {
                char f = s[o];
                for (int p = l; p < n; p += l)
                    if (s[p + o] != f) d = false;
            }
            if (d == true) return true;
        }
        return false;
    }
if (n % l != 0) continue;