最新的Codility时间问题

时间:2013-11-08 21:57:41

标签: c#

刚刚完成最新的Codility,通过它,但没有得到100%

这是规范

字符串S的前缀是S的任何前导连续部分。例如,“c”和“cod”是字符串“codility”的前缀。为简单起见,我们要求前缀非空。 字符串S的前缀P的乘积是P的出现次数乘以P的长度。更确切地说,如果前缀P由K个字符组成并且P在S中恰好出现T次,那么乘积等于K * T. / p>

例如,S =“abababa”具有以下前缀:

"a", whose product equals 1 * 4 = 4,
"ab", whose product equals 2 * 3 = 6,
"aba", whose product equals 3 * 3 = 9,
"abab", whose product equals 4 * 2 = 8,
"ababa", whose product equals 5 * 2 = 10,
"ababab", whose product equals 6 * 1 = 6,
"abababa", whose product equals 7 * 1 = 7.

最长前缀与原始字符串相同。目标是选择这样的前缀以最大化产品的价值。在上面的例子中,最大乘积是10。 在这个问题中,我们只考虑由小写英文字母(a-z)组成的字符串。

基本上,这是一个字符串遍历问题。我能够通过所有验证部分,但我失去了时间。这是我写的

int Solution(string S)
{
     int finalCount = 0;

        for (int i = 0; i <= S.Length - 1; i++)
        {
            string prefix = S.Substring(0, i + 1);
            int count = 0;
            for (int j = 0; j <= S.Length - 1; j++)
            {
                if (prefix.Length + j <= S.Length)
                {
                    string newStr = S.Substring(j, prefix.Length);
                    if (newStr == prefix)
                    {
                        count++;
                    }
                }
                if (j == S.Length - 1)
                {
                    int product = count * prefix.Length;
                    if (product > finalCount)
                    {
                        finalCount = product;
                    }
                }
            }
         }
           return  finalCount;
} 

我知道嵌套循环正在杀死我,但我想不出一种方法来遍历字符串的“部分”而不添加其他循环。

任何帮助都将不胜感激。

4 个答案:

答案 0 :(得分:4)

天真蛮力解决方案需要O(N ** 3)时间。选择从1到N的长度,获取其长度的前缀并通过强力搜索计算出现的次数。 ho长度需要O(N)时间,蛮力需要O(N ** 2)时间,总时间为O(N ** 3)。 如果你使用KMP或Z-algo,你可以在O(N)时间内找到出现,所以整个解决方案将是O(N ** 2)时间。

你可以预先发生,所以需要O(N)+ O(N)= O(N)时间解决方案。

vector<int> z_function(string &S); //z-function, z[0] = S.length()

vector<int> z = z_function(S);
//cnt[i] - count of i-length prefix occurrences of S
for (int i = 0; i < n; ++i) 
  ++cnt[z[i]];

 //if cnt[i] is in S, cnt[i - 1] will be in S
 int previous = 0;
 for (int i = n; i > 0; --i) {
  cnt[i] += previous;
  previous = cnt[i];
 }

这是blog post,解释了所有O(N ** 3),O(N ** 2),O(N)解决方案。

答案 1 :(得分:1)

我的努力如下,试图消除不必要的字符串比较,我读了isaacs博客,但它在c如何转换为c#,我甚至到目前为止使用数组以避免字符串不变性因素但没有改进

        int Rtn = 0;
        int len = S.Length;

        if (len > 1000000000)
            return 1000000000;

        for (int i = 1; i <= len; i++)
        {
            string tofind = S.Substring(0, i);
            int tofindlen = tofind.Length;
            int occurencies = 0;

            for (int ii = 0; ii < len; ii++)
            {
                int found = FastIndexOf(S, tofind.ToCharArray(), ii);
                if (found != -1)
                {
                    if ((found == 0 && tofindlen != 1) || (found >= 0))
                    {
                        ii = found;
                    }
                    ++occurencies ;
                }
            }
            if (occurencies > 0)
            {
                int total = occurencies * tofindlen;

                if (total > Rtn)
                {
                    Rtn = total;
                }
            }
        }
        return Rtn;
    }


    static int FastIndexOf(string source, char[] pattern, int start)
    {

        if (pattern.Length == 0) return 0;
        if (pattern.Length == 1) return source.IndexOf(pattern[0], start);
        bool found;
        int limit = source.Length - pattern.Length + 1 - start;
        if (limit < 1) return -1;

        char c0 = pattern[0];
        char c1 = pattern[1];
        // Find the first occurrence of the first character
        int first = source.IndexOf(c0, start, limit);

        while ((first != -1) && (first + pattern.Length <= source.Length))
        {
            if (source[first + 1] != c1)
            {
                first = source.IndexOf(c0, ++first);
                continue;
            }
            found = true;
             for (int j = 2; j < pattern.Length; j++)
                if (source[first + j] != pattern[j])
                {
                    found = false;
                    break;
                }
            if (found) return first;
            first = source.IndexOf(c0, ++first);
        }
        return -1;
    }

答案 2 :(得分:0)

我只有43 ...我喜欢我的代码! javascript中的相同脚本得到了56它的价值。

using System;

class Solution
{
    public int solution(string S)
    {

    int highestCount = 0;

    for (var i = S.Length; i > 0; i--)
    {
        int occurs = 0;
        string prefix = S.Substring(0, i);    
        int tempIndex = S.IndexOf(prefix) + 1;             
        string tempString = S;            

        while (tempIndex > 0)
        {
            tempString = tempString.Substring(tempIndex);
            tempIndex = tempString.IndexOf(prefix);                                
            tempIndex++;
            occurs++;                                          
        }

        int product = occurs * prefix.Length;

        if ((product) > highestCount)
        {
            if (highestCount >  1000000000)              
                return 1000000000;                           
            highestCount = product;
        }
    }

    return highestCount;

}

}

答案 3 :(得分:0)

效果更好

    private int MaxiumValueOfProduct(string input)
    {
        var positions = new List<int>();
        int max = 0;
        for (int i = 1; i <= input.Length; i++)
        {
            var subString = input.Substring(0, i);
            int position = 0;
            while ((position < input.Length) &&
                   (position = input.IndexOf(subString, position, StringComparison.OrdinalIgnoreCase)) != -1)
            {
                positions.Add(position);
                ++position;
            }

            var currentMax = subString.Length * positions.Count;
            if (currentMax > max) max = currentMax;
            positions.Clear();
        }

        return max;
    }