Skip to Content

Irreducible Anagrams

Editorial oficial (C++) 

Explicación

Primero, podemos considerar el caso en que l=rl = r, es decir, la subcadena tiene longitud 11. Un anagrama reducible requiere que la subcadena se parta en k2k \geq 2 segmentos, lo cual es imposible para longitud 11. Así, una subcadena de longitud 11 tiene un anagrama irreducible.

En los casos siguientes, lrl \neq r.

Consideramos el caso en que s[l]s[r]s[l] \neq s[r]. Podemos crear un anagrama en el que todas las ocurrencias de s[r]s[r] están al frente, y el resto de la cadena sigue. Este es un anagrama irreducible. Podemos asegurarnos de que el último segmento no contenga ocurrencias de s[r]s[r]. Esto es posible porque todas las ocurrencias están al frente.

Para ilustrarlo, consideremos el escenario en que nuestra cadena es abbbb\text{abbbb}. Podemos crear el anagrama bbbba\text{bbbba}. Este anagrama es irreducible porque para incluir a\text{a}, debemos usar la cadena entera, lo que muestra que no se puede reducir.

A continuación, consideramos el caso en que s[l]=s[r]s[l] = s[r]. Que la subcadena tenga o no un anagrama irreducible varía de un caso a otro.

Empecemos por el caso en que la subcadena solo contiene un carácter distinto. Esto no tiene un anagrama irreducible porque su único anagrama es ella misma. Como su único anagrama es ella misma, cualesquiera segmentos que elijamos siempre serán anagramas entre sí, lo que significa que solo tiene un anagrama reducible.

De los ejemplos anteriores se ve que tener t[l]=s[l]t[l]=s[l] y/o t[r]=s[r]t[r]=s[r] no ayuda a crear un anagrama irreducible. Si esto ocurre, podemos partir la cadena en dos segmentos, uno de longitud uno en ll o en rr, y otro con todo lo demás. Por ejemplo, s=abccas=\text{abcca}, aabcc\text{aabcc} no es un anagrama irreducible porque podemos tener un segmento [0,0][0, 0] y otro [1,4][1, 4]. Así, es óptimo tener t[l]s[l]t[l]\neq s[l] Y t[r]s[r]t[r]\neq s[r].

Consideremos el caso en que ss tiene dos caracteres distintos, y sea tt un anagrama irreducible de ss. Además, sea s[0]=as[0] = \text{a}. La misma explicación aplica cuando s[0]=bs[0] = \text{b}, pero las letras estarán intercambiadas (ab y ba\text{a}\to\text{b y b}\to\text{a}).

Definamos xx como la posición más a la izquierda donde el número de b\text{b}s en s[0:x]s[0:x] es mayor o igual que el número de b\text{b}s en t[0:x]t[0:x]. xx es la posición donde el número de b\text{b}s en ss es igual al número de b\text{b}s en tt: cuanto más a la derecha se va, más b\text{b}s se obtienen, así que la primera posición en que esta condición se cumple es cuando el número de b\text{b}s es igual. Como solo tenemos dos caracteres distintos, el número de a\text{a}s también debe ser el mismo. Si tenemos x+1x+1 caracteres en total y un número de b\text{b}s, que llamamos nn, debemos tener x+1n ax + 1 - n \ \text{a}s en ambas cadenas. Así, s[0:x]s[0:x] y t[0:x]t[0:x] también son anagramas: si hay el mismo número de a\text{a}s en ss y tt, y de b\text{b}s en ss y tt, entonces deben ser anagramas. Como el primer y el último carácter son iguales, lo que significa que el último carácter es a\text{a}, sabemos que xx debe estar antes del último carácter, porque agregar una a\text{a} no ayuda a aumentar el conteo de b\text{b}s. Esto implica la existencia de otro anagrama.

Dado que existe un anagrama en [0:x][0:x], sabemos que tt es un anagrama reducible, una contradicción con lo que afirmamos antes. La subcadena restante también debe ser un anagrama porque el número de a\text{a}s en ss y tt es igual, y el de b\text{b}s en ss y tt también es igual. En esencia, es decir alguˊn nuˊmerootro nuˊmero=alguˊn nuˊmerootro nuˊmero\text{algún número} - \text{otro número} = \text{algún número} - \text{otro número}, donde alguˊn nuˊmero\text{algún número} puede ser el número total de a\text{a}s o b\text{b}s, y otro nuˊmero\text{otro número} puede ser el número de ese mismo carácter que había en [0:x][0:x]. El lado izquierdo y el lado derecho pueden representar ss y tt.

El caso en que existen tres caracteres distintos es un poco más complicado. Para asegurar que el primer carácter de ss y de un anagrama sean distintos, podemos insertar al frente todas las ocurrencias del último carácter distinto en aparecer. Luego, para asegurar que el último carácter de ss y de un anagrama sean distintos, podemos insertar todas las ocurrencias del último carácter después del último carácter distinto, si son distintos (si son el mismo, no hace falta hacer nada). Ahora podemos insertar el resto de la cadena en cualquier orden. Este anagrama es irreducible. El último carácter de ss será uno de los primeros caracteres de tt, lo que nos obliga a usar la cadena entera si queremos crear un anagrama.

Podemos generalizar estas observaciones: una cadena tiene al menos un anagrama irreducible si se cumple alguna de estas tres condiciones:

  1. La cadena tiene tres o más caracteres distintos
  2. El primer y el último carácter son distintos
  3. La cadena tiene longitud 1

Las últimas dos condiciones son fáciles de comprobar. Sin embargo, para comprobar la primera, debemos usar sumas de prefijos. Para cada una de las 26 letras del alfabeto, podemos guardar una suma de prefijos que cuente cuántas veces se ha visto la letra. Si en un intervalo se han visto al menos una vez tres letras, entonces la cadena es un anagrama irreducible.

Implementación

Complejidad temporal: O(s+q)\mathcal{O}(|s| + q) donde s|s| es la longitud de la cadena ss y qq es el número de consultas

#include <bits/stdc++.h> using namespace std; const int LETTERS = 26; int main() { string s; cin >> s; vector<array<int, LETTERS>> pref(s.length() + 1); for (int i = 1; i < s.length() + 1; i++) { pref[i] = pref[i - 1]; char let = s[i - 1]; pref[i][let - 'a']++; } int t; cin >> t; while (t--) { int a, b; cin >> a >> b; int num_diff = 0; for (int i = 0; i < LETTERS; i++) { if (pref[b][i] - pref[a - 1][i] > 0) { num_diff++; } } if (b == a || num_diff >= 3 || s[a - 1] != s[b - 1]) { cout << "Yes" << "\n"; } else { cout << "No" << "\n"; } } }