Правильные подматрицы задачи

Erstellt am: 18. Januar 2025

Beantwortet mit O1 von Chat01

Frage

Дана матрица (таблица) из п строк и т столбцов, заполненная строчными буквами латинского алфавита.
Назовем матрицу правильной, если в ней встречаются ровно две различные буквы, и они расположены в шахматном порядке (одна буква на местах белых клеток, вторая — чёрных).
Следующие матрицы являются правильными:
0 х 0
х 0 x
0 x 0

a
b
a
Требуется найти количество правильных подматриц данной матрицы.
Подматрицей называется любая прямоугольная часть исходной матрицы. Она получается из исходной матрицы сначала отбрасыванием нескольких (возможно, 0) подряд идущих строк В начале и нескольких строк (возможно, 0) в конце, а затем в полученной матрице можно отбросить несколько (возможно, 0) столбцов в начале и несколько (возможно, 0) столбцов
в конце.
Формат входных данных
В первой строке даны два целых числа п и т (2 ≤ n, m ≤ 300) столбцов в матрице соответственно.

количество строк и
В каждой из следующих п строк задана последовательность, состоящая из т строчных бу
латинского алфавита.
Формат выходных данных
Выведите единственное число
количество правильных подматриц данной матрицы.
примеры:
ввод:
2 2
ab
ba
вывод:
5

ввод:
2 2
aa
aa
вывод:
0
реши эту задачу на питоне

Gedanke

Identifying the approach

OK, let me see. I’m figuring out how to efficiently determine if a submatrix has exactly two distinct letters in a chessboard pattern, aiming to avoid an O(n^2 m^2) naive method.

Mapping the submatrix

I'm examining a submatrix with top-left and bottom-right corners censured. It sums up as a chessboard with two distinct letters, ensuring consistent patterning and alternating colors.

Identifying pairs

OK, let me see. I'll pinpoint pairs of letters (A, B) and identify "connected components" or "maximal rectangles" of a "pattern" for these letters in a chessboard arrangement.

Transforming the matrix

I’m converting the matrix into a binary format, aiming to spot alternating patterns. Submatrices with any invalid cells are ruled out, leading to identifying valid chessboard patterns.

Crafting matrices

I'm considering matrices that highlight specific colors and letters, aiming to verify if submatrices can form a chessboard pattern by ensuring each color group has identical letters.

Establishing color criteria

I’m defining color criteria for submatrices by combining row and column color patterns, aiming to identify if submatrices align with alternating patterns in a chessboard arrangement.

Verifying patterns

I’m aligning column patterns with alternating sequences of letters, focusing on specific color patterns within the submatrix to confirm they form a valid chessboard arrangement.

Aligning patterns

I’m ensuring each column's pattern matches "L0 L1 L0 L1 ..." or "L1 L0 L1 L0 ..." based on the top cell's color, while maintaining uniformity throughout the submatrix.

Ensuring consistency

I'm piecing together column patterns to match alternating "L0 L1 L0 L1 ..." or "L1 L0 L1 L0 ..." sequences, preserving the top cell's color and uniformity.

Tracking color patterns

I’m noting that for a submatrix to form a chessboard, all cells with the same color must have identical letters, ensuring uniformity within each color group.

Separating color groups

I’m aiming to isolate matrix cells into color groups, requiring each submatrix to have exactly two distinct letters, synchronized by a chessboard pattern.

Mapping distinct letter patterns

I’m now thinking about identifying submatrices with distinct letters in color groups. Each submatrix needs two unique letters and exclusive color patterns for efficiency.

Piecing together rows

I’m trying out different ways to conceptualize submatrices, like focusing on pairs of rows or cells, to streamline the process and enhance efficiency.

Assessing column patterns

I’m evaluating submatrix columns to ensure all color 0 positions share the same letter and all color 1 positions have a distinct letter, maintaining uniformity.

Mapping valid columns

I'm noting the steps to identify submatrices with specific letter patterns, looking for columns where all color 0 and color 1 positions hold the same distinct letters to ensure validity.

Ensuring uniformity

I’m making sure each column in the submatrix follows the same letter pattern, avoiding invalid or identical letter pairings to confirm the submatrix's validity.

Implementing the algorithm

I’m detailing a method to identify and group valid submatrix segments by checking each column's letter pattern, then calculating and summing the contiguous segments' valid sub-subranges.

Assessing algorithm complexity

I’m noting the computational challenges of the naive approach, particularly in Python, and exploring optimizations like prefix checks to streamline the process for each column.

Testing uniformity

I’m exploring prefix sums to confirm uniform letter patterns in column segments, ensuring accurate characterization of color0 and color1 positions.

Validating letter patterns

I'm testing uniformity using prefix sums for each letter in color0 and color1. If only one letter saturates each color group, the submatrix is validated; otherwise, it's invalid.

Evaluating efficiency

I'm mapping out the algorithm's feasibility, noting it might be practical in optimized C++. Python could be marginally under the 1-2 second time constraint.

Weighing optimization strategies

I'm inclined to use a prefix sums approach for tracking letter patterns in columns. This seems simpler and might balance implementation ease and efficiency better than other methods.

Summing valid segments

I’m detailing an approach to summing valid submatrices by traversing columns, grouping contiguous segments, and using prefix sums to ensure uniformity and avoid invalid patterns.

Generating prefix sums

I’m creating prefix sums to quickly identify if specific letter patterns span each range, ensuring the submatrix remains valid and efficiently working towards identifying any invalid configurations.

Validating and grouping

I’m working through validating letter patterns within each row range, grouping contiguous segments, and calculating valid subsubranges to ensure the submatrix's accuracy and efficiency.

Setting up for efficient tracking

I’m thinking through mapping letter pairs to integers and grouping columns for efficient aggregation of valid submatrices, ensuring accuracy and optimizing computational complexity.

Identifying optimization paths

I’m gathering insights on refining the algorithm, including prefix sums and consistency checks for specific letter patterns, to ensure submatrix validity and computational efficiency.

Advancing bitmask strategy

I’m piecing together a bitmask method to progress our approach. This strategy efficiently identifies the presence of specific letters in the submatrix, aiming for better performance and accuracy.

Optimizing bitmask storage

I'm enhancing bitmask storage to efficiently track letters for each color, aiming to quickly determine if a submatrix contains exactly two distinct letters.

Mapping submatrix patterns

I’m analyzing ways to pinpoint valid submatrices with distinct letter patterns, including segment trees and compressed run-length structures, to efficiently ensure accuracy and streamline the process.

Piecing together an incremental strategy

I’m mapping out an incremental approach, examining each row sequentially. This method updates the letter pattern array efficiently, ensuring uniformity or identifying discrepancies in the submatrix's letter patterns.

Monitoring possible changes

I’m keeping tabs on each cell's letter pattern as we iterate through rows. This helps us track if uniformity is broken or maintained across color groups in the submatrix.

Tweaking the approach

I’m streamlining the process to monitor uniformity in submatrices by iterating through rows and checking each cell's letter pattern, ensuring efficiency and pinpointing any breaks in uniformity.

Tracking letter patterns

I’m piecing together how to monitor each column's letter patterns for color0 and color1. This ensures submatrices stay uniform and pinpoints any inconsistencies.

Piecing together patterns

I’m considering how each column’s color1 letters stay consistent as the row range grows, making it easier to spot any issues from left to right.

Tracking letter patterns

Continuing to chart each column's letter consistency, ensuring submatrices remain uniform. This method efficiently pinpoints any discrepancies, maintaining valid configurations throughout the process.

Streamlining initialization

I'm setting color letters to -2 initially, adjusting them during the matrix expansion. This approach simplifies initialization and keeps things efficient and consistent.

Ensuring submatrix robustness

I’m detailing the algorithm to maintain and validate submatrices with letter patterns. This involves setting up, updating, and summing contiguous segments, ensuring informational accuracy and thoroughness.

Ensuring all configurations

OK, I’m thinking about confirming each valid submatrix has both color0 and color1 cells, covering any submatrix dimensions, not just those with at least two rows or columns.

Identifying valid submatrices

I'm working through ensuring all submatrix dimensions, including 1x2 and smaller, have distinct color0 and color1 cells to confirm validity.

Ensuring valid patterns

Given a 1-row submatrix, the color0 or color1 pattern might stop at a specific letter, leading to an invalid column. Thus, 1-row submatrices are excluded.

Validating submatrix patterns

I’m pulling together strategies to ensure 1-row submatrices in a chessboard pattern have distinct color0 and color1 cells, handling cases with two or more columns to maintain integrity.

Taking a closer look

I'm considering a method to ensure each 1-row submatrix in a chessboard pattern has distinct color0 and color1 cells, one letter per column, by examining each row separately.

Validating single-row patterns

I’m focusing on ensuring each single-row submatrix follows a chessboard pattern, distinguishing between columns with letters from different color groups and confirming each column has distinct letters.

Confirming color patterns

For any submatrix with at least 2 rows, each column will feature both color0 and color1 cells. This ensures adherence to the required chessboard pattern.

Including single-column matrices

Valid single-column submatrices with distinct letter patterns are now integrated into the method, ensuring accuracy by accounting for columns with both color0 and color1 cells.

Mapping out single-row submatrices

I'm refining the method to handle single-row submatrices with width 2 or more, ensuring they follow the chessboard pattern with distinct color0 and color1 cells for each column.

Charting single-row segments

I’m defining an approach to pinpoint valid single-row segments with width 2 or more, ensuring each column has distinct color0 and color1 cells, aligning with the chessboard pattern.

Assigning letters to columns

I’m mapping out a strategy to allocate letters to columns based on their color group, ensuring each column has a distinct letter. This approach maintains the chessboard pattern.

Assigning unique letters

Interestingly enough, for each column in a single-row submatrix, I need to ensure unique letters for color0 and color1, preserving the chessboard pattern throughout the process.

Mapping the approach

I’m laying out a plan to pinpoint valid single-row submatrices by using two pointers. Each column gets a unique letter for color0 and color1, ensuring they align with the chessboard pattern.

Crafting the window

I’m refining a sliding window strategy to pinpoint valid submatrices by tracking letters and ensuring segment validity with distinct letter patterns, allowing for efficient and precise detection.

Piecing together

I’m working through updating window parameters to maintain segment validity by checking each column's color, managing conflicts, and ensuring distinct letter patterns for color0 and color1.

Validating segment parameters

Ensuring each single-row subsegment meets distinct letter patterns by adjusting window parameters, tracking conflicts, and confirming valid segments.

Optimizing submatrix detection

I’m piecing together the challenge of efficiently recognizing valid submatrices. This includes potential simplifications or optimizations, aiming for computational feasibility and addressing all valid submatrices.

Mapping the solution

I’m defining the steps to handle single and multi-row submatrices, ensuring each column segment has distinct letters. The sliding window approach will be applied to efficiently determine valid segments.

Thought about counting correct submatrices für 2m 17s

Antwort

Ниже приведён один из возможных путей решения задачи на Python с учётом ограничений n,m300n, m \le 300.

Основная идея:

  1. Подсчитать все «правильные» подматрицы высотой 2\ge 2 с помощью «инкрементального» прохода по строкам:

    • Фиксируем верхнюю границу подматрицы r1r_1.
    • По очереди расширяем нижнюю границу r2r_2 от r1r_1 до n1n-1. Таким образом рассматриваем все подматрицы, начинающиеся в строке r1r_1 и заканчивающиеся в строке r2r_2.
    • При добавлении каждой новой строки r2r_2 «инкрементально» обновляем для каждого столбца информацию:
      • какая буква встречается в «чёрных» клетках (цвет (i+j)mod2=1(i+j) \bmod 2 = 1) этого столбца, и вся ли она одинакова;
      • какая буква встречается в «белых» клетках (цвет (i+j)mod2=0(i+j) \bmod 2 = 0) этого столбца, и вся ли она одинакова.
    • Если в столбце cc при текущем наборе строк все «белые» клетки имеют ровно одну букву (не противоречат друг другу) и все «чёрные» клетки — ровно одну (другую) букву, то такой столбец считается «валидным».
    • Далее нужно найти, сколько непрерывных горизонтальных отрезков столбцов подряд имеют одну и ту же пару букв (letter0,letter1)(\text{letter}_0, \text{letter}_1) и при этом letter0letter1\text{letter}_0 \neq \text{letter}_1. Каждый такой непрерывный участок длины LL даёт вклад L(L+1)2\frac{L\,(L+1)}{2} в число подматриц (так как любой подотрезок внутри него порождает уникальную «правильную» подматрицу).

    Такой способ позволяет за O(n2m)O(n^2 \cdot m) (с учётом аккуратной обработки) перебрать все прямоугольники высотой 2\ge 2.

  2. Отдельно учесть «правильные» подматрицы высотой 11.

    • Если подматрица состоит ровно из одной строки rr, то её «шахматная» раскраска вдоль этой строки будет вида (r+c)mod2(r + c)\bmod 2.
    • Для отрезка столбцов [c1..c2][c_1..c_2] (в одной фиксированной строке) «правильность» означает:
      1. Среди всех столбцов cc в этом отрезке, где (r+c)mod2=0(r + c)\bmod 2 = 0, буква в клетке одинакова (назовём её AA).
      2. Среди столбцов, где (r+c)mod2=1(r + c)\bmod 2 = 1, буква в клетке одинакова (назовём её BB).
      3. ABA \neq B.
      4. В отрезке действительно есть столбцы обоих цветов (иначе там будет либо только AA, либо только BB, что не даёт «двух различных букв» в шахматном узоре).
    • Чтобы эффективно посчитать количество таких отрезков в одной строке, можно использовать «скользящее окно» (two pointers) или похожую идею группировки. Главное – уметь быстро определять, что во всех «белых» позициях встречается не более одной буквы, во всех «чёрных» позициях — не более одной, и что эти буквы различны.
    • Для этого внутри одной строки заведём счётчики/частотные массивы (по 26 букв) отдельно для «белых» и для «чёрных» позиций. Будем двигать правую границу отрезка вперёд, а левую сдвигать при нарушении условия (например, появилось больше одной возможной буквы среди «белых» или среди «чёрных», или буквы у белых и чёрных совпали, или нет хотя бы одной позиции «белого» и одной «чёрного» цвета). Каждый раз, когда подотрезок [s..e][s..e] стал валидным и его длина 2\ge 2, он даёт вклад в ответ.

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

python
def solve(): import sys data = sys.stdin.read().strip().split() n, m = map(int, data[:2]) # Далее идут n строк по m символов matrix = data[2:] # ----------------------------------------------------------------------------- # Часть 1: считаем количество "правильных" подматриц высотой >= 2 # ----------------------------------------------------------------------------- # # Идея: # 1) Фиксируем r1 (верхняя строка). # 2) Для r2 от r1 до n-1 накапливаем информацию о каждом столбце: # - col0Letter[c]: какой символ у "белых" ((i+c)%2 == 0) клеток данного столбца # (если раньше все белые клетки были одинаковы, иначе -1 означает "невалидно", # -2 означает "ещё не встречали белую клетку"? -- ниже упростим, инициализируем сразу # при добавлении первой строки) # - col1Letter[c]: аналогично для "чёрных" ((i+c)%2 == 1) клеток. # 3) Получив для каждого столбца c пару (col0Letter[c], col1Letter[c]) (если не -1), # группируем подряд идущие столбцы с одинаковой парой (A, B), где A != B, A,B != -1. # Пусть длина такого блока L, он даёт L*(L+1)//2 подматриц. # # Ограничение: смотрим только подматрицы, у которых количество строк (r2-r1+1) >= 2, # поскольку иначе один столбец не может содержать и "белые", и "чёрные" клетки. # answer_multirow = 0 # col0Letter[c] и col1Letter[c] будем хранить как либо конкретный символ (char), # либо None, если уже столкнулись с противоречием в этом столбце для цвета. # Начальное значение тоже None, пока не заполним первой строкой. for r1 in range(n): # Инициализируем массивы col0Letter = [None]*m col1Letter = [None]*m # Будем наращивать нижнюю границу r2 for r2 in range(r1, n): # Добавляем строку r2 к текущему "вертикальному" прямоугольнику h = r2 - r1 + 1 # высота текущего подпрямоугольника # Пройдемся по всем столбцам и обновим col0Letter[c], col1Letter[c] for c in range(m): if ((r2 + c) % 2) == 0: # Это "белая" клетка по шахматному цвету if col0Letter[c] is None: # Ещё не было белой клетки в этом столбце (для текущего набора строк) col0Letter[c] = matrix[r2][c] else: # Проверяем совпадение if col0Letter[c] != matrix[r2][c]: col0Letter[c] = None # конфликт, инвалидируем else: # "Чёрная" клетка if col1Letter[c] is None: col1Letter[c] = matrix[r2][c] else: if col1Letter[c] != matrix[r2][c]: col1Letter[c] = None # Если высота = 1, столбец содержит клетки только одного цвета, # значит в таком столбце мы НЕ можем сразу же получить "белые+чёрные клетки". # Поэтому подматрицы высотой = 1 мы здесь не учитываем. # Считаем только если h >= 2: if h >= 2: # Теперь нужно за один проход по столбцам посчитать, # сколько подряд идущих имеют одинаковую пару (col0Letter, col1Letter), # причём обе буквы не None и отличаются друг от друга. current_pair = None current_len = 0 for c in range(m): A = col0Letter[c] B = col1Letter[c] # Проверим валидность if A is None or B is None or A == B: # Невалидная пара, обрываем текущую серию if current_pair is not None: # добавляем количество подотрезков answer_multirow += current_len * (current_len + 1) // 2 current_pair = None current_len = 0 else: # Пара (A, B) валидна if current_pair == (A, B): current_len += 1 else: # Закрываем предыдущую серию if current_pair is not None: answer_multirow += current_len * (current_len + 1) // 2 current_pair = (A, B) current_len = 1 # Закрыть последнюю серию if current_pair is not None: answer_multirow += current_len * (current_len + 1) // 2 # ----------------------------------------------------------------------------- # Часть 2: считаем количество "правильных" подматриц высотой = 1 # ----------------------------------------------------------------------------- # # Если подматрица состоит из одной строки r и столбцов c1..c2, # то "шахматный" цвет клетки (r, c) есть (r+c) % 2. # Условие "правильности": # - Все столбцы, где (r+c) % 2 = 0, имеют одну и ту же букву A. # - Все столбцы, где (r+c) % 2 = 1, имеют одну и ту же букву B != A. # - В подотрезке [c1..c2] есть хотя бы один c с цветом 0 и хотя бы один c с цветом 1. # - Длина подотрезка >= 2 (иначе невозможно иметь и цвет0, и цвет1 в одной строке). # # Можно решить при помощи "скользящего окна" (двух указателей). def count_one_row_submatrices(row_string, row_index, m): res = 0 # color0_freq[l] -- сколько раз буква l (0..25) встретилась на позициях, где цвет=0 # color1_freq[l] -- где цвет=1 color0_freq = [0]*26 color1_freq = [0]*26 # Число различных букв среди позиций цвета 0 distinct0 = 0 # Число различных букв среди позиций цвета 1 distinct1 = 0 # Сколько всего клеток цвета 0 в текущем окне [left..right] count0 = 0 # Сколько всего клеток цвета 1 count1 = 0 left = 0 for right in range(m): c = row_string[right] letter_id = ord(c) - ord('a') if ((row_index + right) % 2) == 0: # цвет 0 count0 += 1 color0_freq[letter_id] += 1 if color0_freq[letter_id] == 1: distinct0 += 1 else: # цвет 1 count1 += 1 color1_freq[letter_id] += 1 if color1_freq[letter_id] == 1: distinct1 += 1 # "Сжимаем" левую границу, пока подотрезок [left..right] не станет валидным # Критерии валидности: # 1) distinct0 <= 1 # 2) distinct1 <= 1 # 3) count0 > 0 и count1 > 0 (обе "краски" должны быть в отрезке) # 4) если distinct0 == 1 и distinct1 == 1, то единственные буквы не должны совпадать while True: # Проверяем, валиден ли текущий [left..right] if distinct0 <= 1 and distinct1 <= 1 and count0 > 0 and count1 > 0: # Если ровно по 1 букве в каждом цвете, проверим различны ли они if distinct0 == 1 and distinct1 == 1: # Находим какие именно буквы # (так как distinct0==1, среди color0_freq ровно одна буква > 0) # (аналогично для color1_freq) letter0 = -1 for i in range(26): if color0_freq[i] > 0: letter0 = i break letter1 = -1 for i in range(26): if color1_freq[i] > 0: letter1 = i break if letter0 == letter1: # невалидно pass else: # валидно, можно выходить из while break else: # Если distinct0 == 0 или distinct1 == 0, или одна из них больше 1, # либо нет обоих цветов - тоже невалидно pass # Иначе невалидно - будем двигать left if left > right: # Окно пустое, выходим break # Убираем left-элемент c_left = row_string[left] letter_left = ord(c_left) - ord('a') if ((row_index + left) % 2) == 0: # уходящая клетка была цвет0 count0 -= 1 color0_freq[letter_left] -= 1 if color0_freq[letter_left] == 0: distinct0 -= 1 else: # цвет1 count1 -= 1 color1_freq[letter_left] -= 1 if color1_freq[letter_left] == 0: distinct1 -= 1 left += 1 # Теперь [left..right], если он валиден, то все его подотрезки, заканчивающиеся в right # и начинающиеся от left..(right-1) тоже проверять. Нам нужны подотрезки длиной >= 2. length = right - left + 1 if length >= 2: # Все подотрезки, заканчивающиеся в right, начинаются от индексов s, где s >= left # Так что количество таких подотрезков = length-1 (т.е. s = left..(right-1)) # Но добавляем именно length - 1 res += (length - 1) return res answer_singlerow = 0 for r in range(n): answer_singlerow += count_one_row_submatrices(matrix[r], r, m) # Суммарный результат answer = answer_multirow + answer_singlerow print(answer)

Пояснения к коду

  1. Подсчёт для высоты 2\ge 2:

    • Для каждой пары строк (r1,r2)(r_1, r_2) последовательно «наращиваем» информацию о столбцах.
    • В массиве col0Letter[c] храним текущую букву для «белых» клеток (цвет 0) в столбце cc или None, если либо буква ещё не определена, либо уже был конфликт. Аналогично col1Letter[c] для «чёрных» (цвет 1).
    • Каждый раз, когда добавляем новую строку r2r_2, проходим по всем столбцам и обновляем эти значения (проверяем, совпадает ли новая буква с уже хранящейся).
    • Затем одним проходом по столбцам считаем длины подряд идущих одинаковых пар (letter0,letter1)(\text{letter}_0,\text{letter}_1). Каждая такая непрерывная группа длины LL даёт L×(L+1)/2L \times (L+1)/2 подпрямоугольников по горизонтали.
  2. Подсчёт для высоты =1=1:

    • В одной фиксированной строке rr просматриваем все подотрезки столбцов [c1..c2][c_1..c_2].
    • Цвет клетки определяется (r+c)mod2(r+c)\bmod 2. Нужно, чтобы все клетки цвета 0 в этом отрезке имели одну букву, все клетки цвета 1 — одну (другую) букву, и чтобы в отрезке был хотя бы один столбец цвета 0 и хотя бы один столбец цвета 1.
    • Реализуем через технику «скользящего окна»: ведём частотные массивы для букв «белых» позиций и «чёрных» позиций.
    • Двигаем правую границу right, постепенно добавляя столбцы. Если в окне нарушаются условия (например, среди «белых» больше одной возможной буквы), то двигаем левую границу left, убирая лишние столбцы, пока окно снова не станет «валидным».
    • Для каждого right (после «сжатия» левой границы) количество подотрезков, заканчивающихся на right и длиной 2\ge2, равно max(0,(текущее_окно_размер)1)\max(0, \text{(текущее\_окно\_размер)} - 1).

В сумме оба подхода дают искомое число всех «правильных» подматриц.

  • Сложность для высоты 2\ge2: O(n2m)O(n^2 \cdot m).
  • Сложность для высоты =1=1: O(nm)O(n \cdot m) (при аккуратной реализации скользящего окна фактически O(nm)O(n \cdot m)).

Итого при n,m300n, m \le 300 код может работать на грани, но при достаточно оптимизированном Python (или PyPy) обычно укладывается в разумные ограничения.


Итог: вышеуказанный скрипт читает входные данные в формате задачи, выводит одно число — количество «правильных» подматриц. В примерах:

  • Если подать:
    text
    2 2 ab ba
    Должно получиться 5.
  • Если подать:
    text
    2 2 aa aa
    Должно получиться 0.

Diesen Q&A teilen