Рекурсивная функция для сопоставления строки с шаблоном подстановочных знаков

поэтому я целый день пытался решить это задание, просто не могу его получить.

следующая функция принимает 2 строки, 2-я (не 1-я), возможно, содержащая * ' s (звездочки).
Ан * является заменой строки (пустой, 1 символ или более), она может появиться (только в s2) один раз, два раза, больше или вообще не может быть смежной с другой * (ab**c), нет необходимости проверять это.

public static boolean samePattern(String s1, String s2)

возвращает true, если строки та же картина.
Должно быть рекурсивные, не использовать никакие циклы, статические и глобальные переменные. Можно использовать локальные переменные и перегрузку метода.

можно использовать только следующие методы: charAt(i), substring(i), substring(i, j), length().

примеры:

1: TheExamIsEasy; 2: The*xamIs*y → true
1: TheExamIsEasy; 2: Th*mIsEasy* → true
1: TheExamIsEasy; 2: * → true
1: TheExamIsEasy; 2: TheExamIsEasy → true
Один: TheExamIsEasy; 2: The*IsHard → значение false

я попытался сравнить символы один за другим, используя charAt пока звездочка не обнаружена, затем проверьте, является ли звездочка пустой, сравнивая последовательный символ (i+1) С символ s1 на должность i, если true -- продолжить рекурсию с i+1 как счетчик s2 & i как счетчик s1;
если false-продолжить рекурсию с i+1 как счетчики для обоих.
Продолжать эту пока не будет найдена другая звездочка или конец строки.

я не знаю, мой мозг теряет счет вещам, не может сосредоточиться, любой указатели / подсказки? Я в правильном направлении?

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

мой код до сих пор (не делать работу, даже теоретически):

public static boolean samePattern(String s1, String s2) {
    if (s1.equals(s2) || s2 == "*") {
        return true;
    }
    return samePattern(s1, s2, 1);
}
public static boolean samePattern(String s1, String s2, int i)
{
    if (s1.equals(s2))
        return true;
    if (i == s2.length() - 1) // No *'s found -- not same pattern.
        return false;

    if (s1.substring(0, i).equals(s2.substring(0, i)))
        samePattern(s1, s2, i+1);
    else if (s2.charAt(i-1) == '*')
        samePattern(s1.substring(0, i-1), s2.substring(0, i), 1); // new smaller strings.
    else
        samePattern(s1.substring(1), s2, i);
}

4 ответов


вот некоторые Python "psudocode", которые могут помочь

def samePattern(s1,s2):
    if s2 == "*" or s1 == s2: return True
    if s1 == "": return False
    if s1[0] == s2[0]: return samePattern(s1[1:], s2[1:])
    if s2[0] == "*": return samePattern(s1, s2[1:]) or samePattern(s1[1:], s2)
    return False

Вот примерное руководство по преобразованию кода

s[0] = the first character
s[1:] = the string minus the first character

проблема с вашим текущим подходом заключается в том, что он не учитывает все возможные подстроки, которые a * может соответствовать. Например, samePattern ("ababababab"," a*b") должен возвращать true; * может соответствовать всем, кроме первой и последней буквы строки, но ваш код предполагает, что, поскольку следующая буква b, * соответствует пустой строке.

Я предлагаю думать о samePattern как "потребляющем" две входные строки, когда он ищет совпадение. На каждом шаге samePattern должен нужно только посмотреть на первый символ каждой строки, чтобы решить, соответствует ли на первый символ возможно, и если это так, сделайте рекурсивный вызов, чтобы проверить остальную часть строки. Трюк будет знать, что делать, когда вы достигнете * в строке шаблона, так как он может или не может быть использован для соответствия первому символу в s1. Вам не нужно смотреть на остальную часть строки, чтобы решить, что делать.

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


вот пример решения, написанного на c#. Извините за отсутствие комментариев, но у меня не было времени на них :/ если вы все еще будете нуждаться в них завтра, я могу написать некоторые, но я надеюсь, что вы поймете идею.

 public static bool CompareString(string s1, string s2, bool wildCard)
 {
        // Both strings are empty
        if ((s1.Length == 0) && (s2.Length == 0)) return true;

        // Second string is empty and there is wildCard character
        if (s2.Length == 0 && wildCard) return true;

        //First string is empty. Answer will be true only if all characters in second string are *.
        if (s1.Length == 0 && s2.Length > 0 && s2[0] == '*')
        {
            string newS2 = s2.Remove(0, 1);
            return CompareString(s1, newS2, true);
        }

        // One of the strings is empty, and second one is not.
        if (s1.Length * s2.Length == 0) return false;

        if (wildCard)
        {
            string newS1 = s1.Remove(0, 1);
            if (CompareString(newS1,s2,true) || CompareString(newS1,s2,false))
            {
                return true;
            }
        }
        else
        {
            if (s2[0] == '*')
            {
                string newS2 = s2.Remove(0,1);
                if (CompareString(s1,newS2,true) || CompareString(s1,newS2,false))
                {
                    return true;
                }
            }
            else
            {
                if (s1[0] == s2[0])
                {
                    string newS1 = s1.Remove(0,1);
                    string newS2 = s2.Remove(0,1);
                    return CompareString(newS1,newS2,false);
                }
                else
                {
                    return false;
                }
            }
        }
        return false;
    }

при работе с такими алгоритмами часто стоит разбить проблему на небольшие куски в вашей голове.

поскольку вы анализируете строки, рассмотрите решение на основе символа за символом. Кроме того, поскольку вы не контролируете фактический размер этих строк, ограничьтесь рассмотрением только первого символа строки в любой момент времени. (ну за одним исключением)

Как только вы определили, что персонажи, с которыми вы имеете дело с ордером на дальнейшее расследование остальной части строки,выбросить их; держать их только добавляет сложности, так зачем заморачиваться? (И наоборот, если символы выравнивают несоответствие, вы сделали-правильно?)

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

У меня есть алгоритм, который я взбил (11 строк кода, плюс фигурные скобки), который я могу опубликовать, если вы хотите полное решение, но я не был уверен в вашем сообщении, Если вы хотите получить алгоритм или просто указатели.