Подсчитайте количество встречающихся фраз в строчных предложениях без знаков препинания

#c# #count #frequency #find-occurrences

Вопрос:

Примеры Входных данных:

  • питер предупреждает Пита, чтобы он не ходил на море
  • альфреду следует отправиться на море
  • альберт предупреждает Пита
  • я же говорил тебе не ходить в Диснейленд

Примеры Результатов:

  • 3: перейдите к
  • 2: отправляйтесь к морю
  • 2: не ходить в

Необязательный:

  • Не учитывайте случаи ниже 2.

Мой подход

 public void zähleHäufigkeitWorte(string[] arr, int n)
{
    bool[] visited = new bool[n];

    // Traverse through array elements and 
    // count frequencies 
    for (int i = 0; i < n; i  )
    {

        // Skip this element if already processed 
        if (visited[i] == true)
            continue;

        // Count frequency 
        int count = 1;
        for (int j = i   1; j < n; j  )
        {
            if (arr[i] == arr[j])
            {
                visited[j] = true;
                count  ;
            }
        }
        wort.Add(arr[i],count);
    }
}
 

Как мне расширить, чтобы подсчитать количество вхождений фраз?

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

1. Возможно, вам понадобится Dictionary<string, int> , где ключом является фраза, а значением-счетчик вхождений.

2. @PeterCsala Спасибо за редактирование.

Ответ №1:

Это должно сработать:

 using System;
using System.Collections.Generic;

namespace SO68666232
{
    public class PhraseCounter
    {

        public static Dictionary<string, int> countWordAndPhraseFrequencies(string input)
        {
            var phraseDic = new Dictionary<string, int>();
            string[] tokens = input.Split(' ');
            int ntokens = tokens.Length;
            for (int start = 0; start < ntokens; start  )
            {
                for (int nwords = 1; nwords <= (ntokens- start) ; nwords  )
                {
                    ArraySegment<string> phraseTokens = new ArraySegment<string>(tokens, start, nwords);
                    string phrase = string.Join(" ", phraseTokens);
                    if (phraseDic.ContainsKey(phrase))
                    {
                        phraseDic[phrase]  ;
                    }
                    else
                    {
                        phraseDic[phrase] = 1;
                    }
                }
            }
            // Remove elements with only 1 occurrence
            IEnumerable<string> keys = new List<string>(phraseDic.Keys);
            foreach (string key in keys)
            {
                if (phraseDic[key] <= 1)
                {
                    phraseDic.Remove(key);
                }
            }
            return phraseDic;
        }
    }
}
 

Возможно, это не самый эффективный способ, так как время увеличивается с увеличением количества слов в квадрате, но он работает.

Испытательная программа:

     class Program
    {
        const string sampleInput = "peter warns pete to not go to the sea alfred should go to the sea albert warns pete i told you to not go to disneyland";

        static void Main(string[] args)
        {
            var res = PhraseCounter.countWordAndPhraseFrequencies(sampleInput);
            foreach (string key in res.Keys)
            {
                Console.WriteLine("{0}: {1}", key, res[key]);
            }
            Console.WriteLine("Press any key to continue...");
            Console.ReadKey();
        }
    }
 

Результаты:

 warns: 2
warns pete: 2
pete: 2
to: 5
to not: 2
to not go: 2
to not go to: 2
not: 2
not go: 2
not go to: 2
go: 3
go to: 3
go to the: 2
go to the sea: 2
to the: 2
to the sea: 2
the: 2
the sea: 2
sea: 2
 

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

1. Привет. Я получаю System.OutOfMemoryException string phrase = string.Join(" ", phraseTokens); ответ .

2. Вы используете приведенную здесь тестовую строку или больший ввод? Каков размер вашего вклада? Алгоритм в основном составляет список всех возможных фраз, поэтому, если у вас есть n слов во входных данных, будет O(n^2) возможных фраз средней длины O(n), поэтому требования к памяти увеличиваются по мере увеличения O(n^3). Алгоритм можно было бы легко изменить, чтобы обеспечить максимальную длину фразы, скажем, в 10 слов, тогда требования к памяти были бы значительно снижены.

3. Другой альтернативой было бы изменить алгоритм для немедленного подсчета количества вхождений фразы и сохранения только в том случае, если > 1, вместо накопления каждой фразы и фильтрации в конце.