Это третья часть в серии образовательных статей о регулярных выражениях. Отсюда следует Как это регулярное выражение находит треугольные числа? (где впервые вводятся вложенные ссылки) и Как мы можем сопоставить ^ nb ^ n с регулярным выражением Java? (где более подробно рассматривается механизм «подсчета» упреждающего просмотра). В этой части вводится особая форма вложенного утверждения, которая в сочетании с вложенными ссылками позволяет регулярному выражению Java соответствовать тому, что большинство людей считает «невозможным»: палиндромы !!
Язык палиндромов не регулярный ; это фактически контекстно-свободный (для данного алфавита). Тем не менее, современная реализация регулярных выражений распознает не только обычные языки, а рекурсивные шаблоны Perl / PCRE и балансирующие группы .NET могут легко распознавать палиндромы (см .: Связанные вопросы ).
Однако механизм регулярных выражений Java поддерживает ни одна из этих «продвинутых» функций. И все же "кто-то" ( * wink * ) удалось написать следующее регулярное выражение, которое, похоже, отлично справляется со своей задачей ( см. Также на ideone.com ):
public class Palindrome { // asserts that the entirety of the string matches the given pattern static String assertEntirety(String pattern) { return "(?<=(?=^pattern$).*)".replace("pattern", pattern); } public static void main(String[] args) { final String PALINDROME = "(?x) | (?:(.) add)+ chk" .replace("add", assertEntirety(".*? (\\1 \\2?)")) .replace("chk", assertEntirety("\\2")); System.out.println(PALINDROME); // (?x) | (?:(.) (?<=(?=^.*? (\1 \2?)$).*))+ (?<=(?=^\2$).*) String[] tests = { "", // true "x", // true "xx", // true "xy", // false "xyx", // true "xxx", // true "xxyx", // false "racecar", // true "step on no pets", // true "aManaPlanaCanalPanaMa", // true "this is impossible", // FALSE!!! }; for (String test : tests) { System.out.printf("[%s] %s%n", test, test.matches(PALINDROME)); } } }
Итак кажется, это работает, но как?
Ссылки
java.util.regex.Pattern
- regular-expressions.info/Freespacing
(? x)
, Поисковые запросы(? =…)
/(?
и т. Д.ОБЩИЕ СМЫСЛЫ !!!
Это не лучший способ обнаружения палиндромов; это
O (N ^ 3)
в лучшем случае. Выполнение этого обнаружения на языке программирования более общего назначения является более эффективным и более простым.Вы бы не хотели использовать регулярное выражение для обнаружения палиндромов по тем же причинам, по которым вы не хотели бы ] используйте регулярное выражение , чтобы найти простые числа. Тем не менее, вы бы изучили , как нерекурсивное не балансирующее групповое регулярное выражение может обнаруживать палиндромы по тем же причинам, по которым вы изучили , как регулярное выражение можно использовать для проверки простоты: это весело, это сложно , это познавательно.
Связанные вопросы
- Как проверить, что строка является палиндромом, используя регулярные выражения? - это «невозможно»! (если ...)
- Как проверить, является ли данная строка палиндромом? - решения без регулярных выражений на многих языках
- Как определить, является ли число простым с регулярным выражением?