Поиск символов в строке с помощью хэш-таблицы

#c# #.net #algorithm #hashtable

#c# #.net #алгоритм #хэш-таблица

Вопрос:

Я решил решить проблему поиска заданных символов в строке. И я решил это двумя способами:

Первый (использование хэш-таблицы для сохранения значений в ASCII для символов, которые мы хотим найти):

 static void Hash(string text, char[] charsToFind)
{
    Dictionary<int,char> chars = new Dictionary<int,char>();
    foreach (var letter in charsToFind)
    {
        chars[(int)letter] = letter;
    }

    foreach (var letter in text)
    {
        if (chars.ContainsKey((int)letter))
        {
            if (letter == chars[(int)letter])
            {
                Console.WriteLine("Element found at: {0}, value: {1}", (int)letter, letter);
            }
        }
    }
}
  

И второй способ (наивный):

 static void Naive(string text, char[] charsToFind)
{
    foreach (var letter in text)
    {
        foreach (var character in charsToFind)
        {
            if ((int)letter == (int)character)
            {
                Console.WriteLine("Element found at: {0}, value: {1}", (int)letter, letter);
            }
        }
    }
}
  

И все работает отлично! Вопрос, который я хотел бы задать, заключается в том, какой из них лучше, и есть ли еще лучшие решения этой проблемы?

Заранее спасибо!

Комментарии:

1. Существует ли ограничение «только .NET 2.0» или вы можете свободно использовать 3.5 или 4.0?

2. вы можете использовать любую версию .NET

3. Ваш первый метод неверен. Это должен быть Dict<char,int>, и вы должны заполнить его for(int i = text.Length - 1; i > -1; i--) chars[text[i]] = text[i];

Ответ №1:

Использование LINQ:

 string input = "abc";
char[] charsToFind = new[] { 'a', '1', 'b' };
IEnumerable<int> ids = charsToFind.Select(ch => input.IndexOf(ch)); // { 0, -1, 1 }
  

С Hashset<T> которая является общей хэш-таблицей:

 HashSet<char> set = new HashSet<char>(input.ToCharArray());
...
  

Комментарии:

1. Спасибо! Но является ли мой алгоритм с хэш-таблицей более эффективным и усовершенствованным?

2. 1. .@Tsvetan, ты, вероятно, можешь взять образцы входных данных и проверить время выполнения.

3. Я знаю, но я спрашиваю о том, какой из них лучше с точки зрения практики программирования.

Ответ №2:

Первый подход является лучшим, но второй, вероятно, будет быстрее для небольшого количества символов.

Некоторые комментарии к первому. В первом случае использование словаря связано с затратами на вычисление хэша и выполнение поиска. Если бы вы знали, что символы были ASCII, вы могли бы использовать массив для ускорения поиска.

Вместо выполнения ‘containsKey’ вы могли бы выполнить ‘TryGetValue’ только для поиска один раз.

Комментарии:

1. Я знаю, что символы были ASCII, но я читал, что использование хэш-таблицы было лучшим подходом. Итак, я решил спросить здесь…

2. Да, но хэш-таблица работает медленнее, поскольку ей требуется выполнить больше работы.

3. Интересная вещь, которую я обнаружил, заключается в том, что наивный алгоритм является самым быстрым (~ 0010000ms). Затем это хэш, а после этого LINQ. Тесты были выполнены на 30,7 КБ текста. Я тоже попробую ваш подход и посмотрю, что получится…