идентифицировать повторяющиеся/повторяющиеся шаблоны как подмассивы из родительского массива

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

ex: ['horse', 'camel', 'horse', 'camel', 'tiger', 'horse', 'camel', 'horse', 'camel']

функция должна вернуть

['horse', 'camel'], 
['horse', 'camel', 'horse'],
['camel', 'horse', 'camel'],
['horse', 'camel', 'horse', 'camel']

то есть поиск шаблонов, которые повторяются в массиве, который может стать подмассивом,

Или другой способ определения: -> Найти все подмассивы, которые встречаются более 1 раза в основном массиве.

то есть результирующие массивы должны иметь length > 1 ->

[1, 2, 3, 1, 2, 1, 4, 5] => [1,2,3] и [1,4,5] оба являются подмассивами, но [1,2,3] является повторяющимся/повторяющимся подмассивом, НЕ [1,4,5]

Поиск подходящего эффективного алгоритма вместо решения зацикливания грубой силы.


person Nishutosh Sharma    schedule 19.10.2016    source источник
comment
Уточните, пожалуйста, какой результат вы хотите. Сейчас похоже, что вы хотите вернуть два массива. Лучше, если вы предоставите подробное описание проблемы   -  person pkacprzak    schedule 19.10.2016
comment
@pkacprzak Я отредактировал вопрос, чтобы добавить больше пояснений, дайте мне знать, если теперь это объясняет постановку проблемы.   -  person Nishutosh Sharma    schedule 19.10.2016
comment
Все еще не ясно. Вы должны определить, что для вас означает наличие подмассива в массиве.   -  person pkacprzak    schedule 19.10.2016
comment
@NishutoshSharma, вы пробовали алгоритм поиска цикла Флойда?   -  person Kaidul    schedule 19.10.2016
comment
Отличается ли хороший алгоритм от строкового алгоритма, перечисляющего подстроки? (Подумать дважды.)   -  person greybeard    schedule 19.10.2016
comment
@greybeard, я подумал об этом, прежде чем прийти к такому заключению-› Массив -> ['лошадь', 'верблюд', 'лошадь', 'верблюд', 'тигр', 'лошадь', 'верблюд', 'лошадь ', 'верблюд'] |=> Строка -> лошадь верблюд лошадь верблюд тигр лошадь верблюд лошадь верблюд |=> Подстрока -> лошадь верблюд, орсе пришел, rse верблюд, ...... Это создаст 70-80% отходы для меня. И усложнить читаемость кода. У меня есть еще вопросы в категории подстроки здесь: of-final" title="найти все повторяющиеся подстроки в строке, игнорируя пробелы слева и справа от final"> stackoverflow.com/questions/40111101/. Что сказать ?   -  person Nishutosh Sharma    schedule 19.10.2016
comment
Что, если вы сопоставили слова с символами («лошадь» => «h», «верблюд» => «c», «тигр» => «t»), затем массив слов превратился в строку «hchcthchc» и поискали хорошие решения. for перечислить все повторяющиеся подстроки? (Подумать дважды.)   -  person greybeard    schedule 19.10.2016
comment
@greybeard Это приведет к дополнительным усилиям по выявлению уникальных мнемоник (тигр, тигрица, тарантул), да, как только они у нас появятся, это может найти лучшее решение для подстроки. Почему бы вам не сделать это как ответ с некоторой сутью/логикой/кодом (на любом языке).   -  person Nishutosh Sharma    schedule 19.10.2016
comment
@KaidulIslam Это поиск циклов, это не обязательно цикл, это просто повторение. Я посмотрел на это. будет нормально [1,2,1,2,1,2,3,1,2] -> (1,2) встречается 3 раза в цикле. В то время как я хочу, чтобы все повторения -> (1,2) происходили 4 раза в цикле.   -  person Nishutosh Sharma    schedule 19.10.2016
comment
@pkacprzak Теперь должно быть ясно. Хотя, если мы пойдем по определению, подмассив на самом деле означает часть массива.   -  person Nishutosh Sharma    schedule 19.10.2016
comment
будет ли [camel, horse] включено в вывод?   -  person Bobas_Pett    schedule 20.10.2016
comment
@Bobas_Pett В этом алгоритме. хорошо получить все шаблоны. Как только мы получим все шаблоны и их номер вхождения, их можно будет уточнить позже, я думаю, что это эффективный подход для продвижения принципа единой ответственности. Вместо этого один комок грязи делает все в одном куске. кода.   -  person Nishutosh Sharma    schedule 20.10.2016
comment
Пример [1,2,3,1,2,1,4,5] странен: как [1,2,3], встречающийся ровно один раз, повторяется больше, чем [1,4,5]? А как насчет [1 2 1 2 1] - [1 2] и [2 1] не представляет никакой сложности, но считаете ли вы, что [1 2 1] встречается дважды?   -  person greybeard    schedule 21.10.2016
comment
@greybeard Они перекрываются, поэтому их нельзя рассматривать. Таким образом, все неперекрывающиеся повторяющиеся шаблоны должны быть приняты во внимание.   -  person Nishutosh Sharma    schedule 21.10.2016


Ответы (1)


Вероятно, это не то, что вы хотите, но я еще не знаю, что вы пробовали, поэтому, возможно, это может быть полезно. Вот мой прямой подход, который, вероятно, подпадает под ваши «решения для циклов грубой силы», но я решил попробовать, поскольку никто не опубликовал полный ответ.

В Java:

// use this to not add duplicates to list
static boolean contains (List<String[]> patterns, String[] pattern){
    for(String[] s: patterns)
        if (Arrays.equals(pattern,s)) return true;
    return false;
}


/**
 *
 * @param str String array containing all elements in your set
 * @param start index of subarray
 * @param end index of subarray
 * @return if subarray is a recurring pattern
 */
static boolean search (String[] str,int start,int end) {
    // length of pattern
    int len = end - start + 1;

    // how many times you want pattern to
    // appear in text
    int n = 1;

    // increment m if pattern is matched
    int m = 0;

    // shift pattern down the array
    for (int i = end+1; i <= str.length - len; i++) {
        int j;
        for (j = 0; j < len; j++) {
            if (!str[i + j].equals(str[start + j]))
                break;
        }

        // if pattern is matched at [i to i+len]
        if (j == len) {
            m++;
            if (m == n) return true;
        }
    }
    return false;
}


/**
 *
 * @param str String array containing all elements in your set
 * @return a list of subsets of input set which are a recurring pattern
 */
static List<String[]> g (String[] str) {
    // put patterns in here
    List<String[]> patterns = new ArrayList<>();

    // iterate through all possible subarrays in str
    for(int i = 0; i < str.length-1; i++){
        for(int j = i + 1; j < str.length; j++){

            // if a pattern is found
            if (search(str,i,j)) {
                int len = j-i+1;
                String[] subarray = new String[len];
                System.arraycopy(str,i,subarray,0,len);
                if (!contains(patterns,subarray))
                    patterns.add(subarray);

            }
        }
    }
    return patterns;
}

public static void main(String[] args) {

    String[] str = {"horse", "camel", "horse", "camel", "tiger",
                    "horse", "camel", "horse", "camel"};
    // print out
    List<String[]> patterns = g(str);
    for (String[] s: patterns)
        System.out.println(Arrays.toString(s));
}

Выход:

[horse, camel]
[horse, camel, horse]
[horse, camel, horse, camel]
[camel, horse]
[camel, horse, camel]

Как упоминалось в комментарии, который я опубликовал:

"будет ли [camel, horse] включено в вывод?"

Вывод, который у меня есть, соответствует этому, поскольку есть 2 экземпляра [camel, horse] с индексами [1-2] и [6-7]. Но, может быть, я совершенно неправильно понимаю ваш вопрос и не понимаю ограничений.

Что касается оптимизации, метод search(...), например, представляет собой простой поиск подстроки, есть несколько более оптимизированных способов сделать это, например. Кнут-Моррис-Пратт. Извините, если это было именно то, чего вы не хотели, но, возможно, есть какая-то польза

person Bobas_Pett    schedule 20.10.2016