Kattis挑战:电话列表,超过4秒时间限制,C#

Kattis挑战:电话列表,超过4秒时间限制,C#,c#,performance,time,C#,Performance,Time,使用在线自动测试系统Kattis,我(用C#)面临的挑战是创建一个电话号码列表,然后找出其中是否有前缀 (见:,任务A) 提供答案相对容易,但无论我如何尝试,我都无法逃避得到的结果:超过了时间限制,一些进一步的信息说运行程序(通过自动程序)需要4秒钟以上 我已经试过几次从零开始重写它,我也试过了在互联网上找到的所有现有建议。我发现自己完全不知道该怎么办,主要是因为最终我无法确定到底是什么错了 是在一个类似的问题上提出的(但尚未解决),并没有发挥神奇的作用-但这是迄今为止我见过的最好的: usin

使用在线自动测试系统Kattis,我(用C#)面临的挑战是创建一个电话号码列表,然后找出其中是否有前缀

(见:,任务A)

提供答案相对容易,但无论我如何尝试,我都无法逃避得到的结果:超过了时间限制,一些进一步的信息说运行程序(通过自动程序)需要4秒钟以上

我已经试过几次从零开始重写它,我也试过了在互联网上找到的所有现有建议。我发现自己完全不知道该怎么办,主要是因为最终我无法确定到底是什么错了

是在一个类似的问题上提出的(但尚未解决),并没有发挥神奇的作用-但这是迄今为止我见过的最好的:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PhoneList
{
class Program
{
    static void Main(string[] args)
    {
        // Save number of test cases.
        var numTestCases = int.Parse(Console.ReadLine());

        // Do this for each test case.
        for (int i = 0; i < numTestCases; i++)
        {
            // Save number of phone numbers.
            var numPhoneNumbers = int.Parse(Console.ReadLine());

            // Save all phonenumbers in the list.
            var phoneNumbersList = new List<string>();
            for (int j = 0; j < numPhoneNumbers; j++)
            {
                string number = Console.ReadLine().Trim();

                // Add to list.
                phoneNumbersList.Add(number);
            }

            // Write output.
            if (phoneNumbersList.All(n => !phoneNumbersList.Except(new[] { n }).Any(o => o.StartsWith(n))))
            {
                Console.WriteLine("YES");
            }
            else
            {
                Console.WriteLine("NO");
            }
        }
    }
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
命名空间电话列表
{
班级计划
{
静态void Main(字符串[]参数)
{
//保存测试用例的数量。
var numTestCases=int.Parse(Console.ReadLine());
//对每个测试用例执行此操作。
对于(int i=0;i!phoneNumbersList.Except(new[]{n}).Any(o=>o.StartsWith(n)))
{
控制台。WriteLine(“是”);
}
其他的
{
控制台。写入线(“否”);
}
}
}
}
}

有什么建议吗?

您是否尝试过在添加所有电话号码后对电话号码列表进行排序(按字母顺序),然后检查项目n+1是否以项目n开头

phoneNumbersList.Sort((x,y) => string.Compare(x, y));

var consistent = true;
for (var j = 0; j < phoneNumbersList.Count - 1; ++j)
{
   if (phoneNumbersList[j + 1].StartsWith(phoneNumbersList[j]))
   {
        consistent = false;
        break;
   }
}

Console.WriteLine(consistent ? "YES" : "NO");
phoneNumbersList.Sort((x,y)=>string.Compare(x,y));
var一致=真;
对于(var j=0;j
添加所有电话号码后,您是否尝试过对电话号码列表进行排序(按字母顺序),然后检查项目n+1是否以项目n开头

phoneNumbersList.Sort((x,y) => string.Compare(x, y));

var consistent = true;
for (var j = 0; j < phoneNumbersList.Count - 1; ++j)
{
   if (phoneNumbersList[j + 1].StartsWith(phoneNumbersList[j]))
   {
        consistent = false;
        break;
   }
}

Console.WriteLine(consistent ? "YES" : "NO");
phoneNumbersList.Sort((x,y)=>string.Compare(x,y));
var一致=真;
对于(var j=0;j
不总是最短的,最好的才是最好的:-)尝试以下方法:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Samples
{
    class PhoneListProcessor
    {
        const int MaxCount = 10000;
        const int MaxDigits = 10;
        Dictionary<int, bool> phoneNumberInfo = new Dictionary<int, bool>(MaxCount * MaxDigits);
        public bool Process(IEnumerable<string> phoneNumbers, bool readToEnd)
        {
            phoneNumberInfo.Clear();
            using (var e = phoneNumbers.GetEnumerator())
            {
                while (e.MoveNext())
                {
                    if (Process(e.Current)) continue;
                    if (readToEnd)
                    {
                        while (e.MoveNext()) { }
                    }
                    return false;
                }
            }
            return true;
        }
        bool Process(string phoneNumber)
        {
            var phoneNumberInfo = this.phoneNumberInfo;
            int phoneCode = 0;
            int digitPos = 0;
            bool hasSuffix = true;
            while (true)
            {
                phoneCode = 11 * phoneCode + (phoneNumber[digitPos] - '0' + 1);
                bool isLastDigit = ++digitPos >= phoneNumber.Length;
                bool isPhoneNumber;
                if (hasSuffix && phoneNumberInfo.TryGetValue(phoneCode, out isPhoneNumber))
                {
                    if (isPhoneNumber || isLastDigit) return false;
                }
                else
                {
                    phoneNumberInfo.Add(phoneCode, isLastDigit);
                    if (isLastDigit) return true;
                    hasSuffix = false;
                }
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var processor = new PhoneListProcessor();
            int testCount = int.Parse(Console.ReadLine());
            for (int testIndex = 0; testIndex < testCount; testIndex++)
            {
                int count = int.Parse(Console.ReadLine());
                var numbers = Enumerable.Range(0, count).Select(_ => Console.ReadLine());
                bool readToEnd = testIndex + 1 < testCount;
                bool valid = processor.Process(numbers, readToEnd);
                Console.WriteLine(valid ? "YES" : "NO");
            }
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
名称空间示例
{
类PhoneListProcessor
{
const int MaxCount=10000;
const int MaxDigits=10;
字典phoneNumberInfo=新字典(MaxCount*MaxDigits);
公共bool进程(IEnumerable phonenumber,bool readToEnd)
{
phoneNumberInfo.Clear();
使用(var e=phoneNumbers.GetEnumerator())
{
while(如MoveNext())
{
如果(流程(如当前))继续;
如果(readToEnd)
{
而(e.MoveNext()){}
}
返回false;
}
}
返回true;
}
bool进程(字符串电话号码)
{
var phoneNumberInfo=this.phoneNumberInfo;
int phoneCode=0;
int-digitPos=0;
bool hasuffix=true;
while(true)
{
phoneCode=11*phoneCode+(电话号码[digitPos]-“0”+1);
bool isLastDigit=++digitPos>=phoneNumber.Length;
布尔伊斯彭纳姆伯;
if(hasSuffix&&phoneNumberInfo.TryGetValue(phoneCode,out-isPhoneNumber))
{
if(isPhoneNumber | | isLastDigit)返回false;
}
其他的
{
添加(电话号码,isLastDigit);
if(isLastDigit)返回true;
hasSuffix=假;
}
}
}
}
班级计划
{
静态void Main(字符串[]参数)
{
var processor=新的PhoneListProcessor();
int testCount=int.Parse(Console.ReadLine());
对于(int-testIndex=0;testIndexConsole.ReadLine());
bool readToEnd=testIndex+1

基本上,is所做的是动态构建,并在任务约束和细节下使用a的变体。每个电话号码或前缀都被编码为基数为11的整数,不带零(每个数字都递增,因此我们没有0-9,而是1-10),以便根据要求区分带前导零的数字和不带前导零的数字。

不总是最短和最细的是最好的:-)尝试以下方法:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Samples
{
    class PhoneListProcessor
    {
        const int MaxCount = 10000;
        const int MaxDigits = 10;
        Dictionary<int, bool> phoneNumberInfo = new Dictionary<int, bool>(MaxCount * MaxDigits);
        public bool Process(IEnumerable<string> phoneNumbers, bool readToEnd)
        {
            phoneNumberInfo.Clear();
            using (var e = phoneNumbers.GetEnumerator())
            {
                while (e.MoveNext())
                {
                    if (Process(e.Current)) continue;
                    if (readToEnd)
                    {
                        while (e.MoveNext()) { }
                    }
                    return false;
                }
            }
            return true;
        }
        bool Process(string phoneNumber)
        {
            var phoneNumberInfo = this.phoneNumberInfo;
            int phoneCode = 0;
            int digitPos = 0;
            bool hasSuffix = true;
            while (true)
            {
                phoneCode = 11 * phoneCode + (phoneNumber[digitPos] - '0' + 1);
                bool isLastDigit = ++digitPos >= phoneNumber.Length;
                bool isPhoneNumber;
                if (hasSuffix && phoneNumberInfo.TryGetValue(phoneCode, out isPhoneNumber))
                {
                    if (isPhoneNumber || isLastDigit) return false;
                }
                else
                {
                    phoneNumberInfo.Add(phoneCode, isLastDigit);
                    if (isLastDigit) return true;
                    hasSuffix = false;
                }
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var processor = new PhoneListProcessor();
            int testCount = int.Parse(Console.ReadLine());
            for (int testIndex = 0; testIndex < testCount; testIndex++)
            {
                int count = int.Parse(Console.ReadLine());
                var numbers = Enumerable.Range(0, count).Select(_ => Console.ReadLine());
                bool readToEnd = testIndex + 1 < testCount;
                bool valid = processor.Process(numbers, readToEnd);
                Console.WriteLine(valid ? "YES" : "NO");
            }
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
名称空间示例
{
类PhoneListProcessor
{
const int MaxCount=10000;
常量int MaxDi