fork download
  1.  
  2. import java.io.*;
  3. import java.util.*;
  4.  
  5. public class Main {
  6.  
  7. static class EntradaRapida {
  8. private final BufferedInputStream entrada =
  9.  
  10. private final byte[] buffer = new byte[1 << 16];
  11. private int posicion = 0;
  12. private int cantidad = 0;
  13.  
  14. private int leer() throws IOException {
  15. if (posicion >= cantidad) {
  16. cantidad = entrada.read(buffer);
  17. posicion = 0;
  18.  
  19. if (cantidad <= 0) return -1;
  20. }
  21.  
  22. return buffer[posicion++];
  23. }
  24.  
  25. int leerEntero() throws IOException {
  26. int caracter;
  27.  
  28. do {
  29. caracter = leer();
  30. if (caracter == -1) return -1;
  31. } while (caracter <= 32);
  32.  
  33. int numero = 0;
  34.  
  35. while (caracter > 32) {
  36. numero = numero * 10 + caracter - '0';
  37. caracter = leer();
  38. }
  39.  
  40. return numero;
  41. }
  42.  
  43. String leerCadena() throws IOException {
  44. StringBuilder resultado = new StringBuilder();
  45. int caracter;
  46.  
  47. do {
  48. caracter = leer();
  49. if (caracter == -1) return null;
  50. } while (caracter <= 32);
  51.  
  52. while (caracter > 32) {
  53. resultado.append((char) caracter);
  54. caracter = leer();
  55. }
  56.  
  57. return resultado.toString();
  58. }
  59. }
  60.  
  61. static int[] construirSuffixArray(int[] texto) {
  62. int longitud = texto.length;
  63.  
  64. int[] sufijos = new int[longitud];
  65. int[] clases = new int[longitud];
  66. int[] auxiliar = new int[longitud];
  67. int[] nuevasClases = new int[longitud];
  68.  
  69. int maximoSimbolo = 0;
  70.  
  71. for (int valor : texto) {
  72. maximoSimbolo = Math.max(maximoSimbolo, valor);
  73. }
  74.  
  75. int[] frecuencias = new int[
  76. Math.max(longitud, maximoSimbolo + 1)
  77. ];
  78.  
  79. for (int valor : texto) {
  80. frecuencias[valor]++;
  81. }
  82.  
  83. for (int i = 1; i <= maximoSimbolo; i++) {
  84. frecuencias[i] += frecuencias[i - 1];
  85. }
  86.  
  87. for (int i = longitud - 1; i >= 0; i--) {
  88. sufijos[--frecuencias[texto[i]]] = i;
  89. }
  90.  
  91. int cantidadClases = 1;
  92. clases[sufijos[0]] = 0;
  93.  
  94. for (int i = 1; i < longitud; i++) {
  95. if (texto[sufijos[i]] != texto[sufijos[i - 1]]) {
  96. cantidadClases++;
  97. }
  98.  
  99. clases[sufijos[i]] = cantidadClases - 1;
  100. }
  101.  
  102. for (int distancia = 1;
  103. distancia < longitud;
  104. distancia <<= 1) {
  105.  
  106. for (int i = 0; i < longitud; i++) {
  107. auxiliar[i] = sufijos[i] - distancia;
  108.  
  109. if (auxiliar[i] < 0) {
  110. auxiliar[i] += longitud;
  111. }
  112. }
  113.  
  114. Arrays.fill(frecuencias, 0, cantidadClases, 0);
  115.  
  116. for (int i = 0; i < longitud; i++) {
  117. frecuencias[clases[auxiliar[i]]]++;
  118. }
  119.  
  120. for (int i = 1; i < cantidadClases; i++) {
  121. frecuencias[i] += frecuencias[i - 1];
  122. }
  123.  
  124. for (int i = longitud - 1; i >= 0; i--) {
  125. int indice = auxiliar[i];
  126. int clase = clases[indice];
  127.  
  128. sufijos[--frecuencias[clase]] = indice;
  129. }
  130.  
  131. nuevasClases[sufijos[0]] = 0;
  132.  
  133. int totalNuevasClases = 1;
  134.  
  135. for (int i = 1; i < longitud; i++) {
  136. int actual = sufijos[i];
  137. int anterior = sufijos[i - 1];
  138.  
  139. int segundoActual = actual + distancia;
  140. int segundoAnterior = anterior + distancia;
  141.  
  142. if (segundoActual >= longitud) {
  143. segundoActual -= longitud;
  144. }
  145.  
  146. if (segundoAnterior >= longitud) {
  147. segundoAnterior -= longitud;
  148. }
  149.  
  150. if (clases[actual] != clases[anterior] ||
  151. clases[segundoActual] != clases[segundoAnterior]) {
  152.  
  153. totalNuevasClases++;
  154. }
  155.  
  156. nuevasClases[actual] = totalNuevasClases - 1;
  157. }
  158.  
  159. int[] intercambio = clases;
  160. clases = nuevasClases;
  161. nuevasClases = intercambio;
  162.  
  163. cantidadClases = totalNuevasClases;
  164.  
  165. if (cantidadClases == longitud) {
  166. break;
  167. }
  168. }
  169.  
  170. return sufijos;
  171. }
  172.  
  173. static int[] construirLCP(int[] texto, int[] sufijos) {
  174. int longitud = texto.length;
  175.  
  176. int[] posiciones = new int[longitud];
  177. int[] lcp = new int[longitud];
  178.  
  179. for (int i = 0; i < longitud; i++) {
  180. posiciones[sufijos[i]] = i;
  181. }
  182.  
  183. int compartidos = 0;
  184.  
  185. for (int i = 0; i < longitud; i++) {
  186. int rango = posiciones[i];
  187.  
  188. if (rango == 0) {
  189. compartidos = 0;
  190. continue;
  191. }
  192.  
  193. int anterior = sufijos[rango - 1];
  194.  
  195. while (i + compartidos < longitud &&
  196. anterior + compartidos < longitud &&
  197. texto[i + compartidos] ==
  198. texto[anterior + compartidos]) {
  199.  
  200. compartidos++;
  201. }
  202.  
  203. lcp[rango] = compartidos;
  204.  
  205. if (compartidos > 0) {
  206. compartidos--;
  207. }
  208. }
  209.  
  210. return lcp;
  211. }
  212.  
  213. static int[] construirTexto(
  214. String cadenaS,
  215. String cadenaT,
  216. int n
  217. ) {
  218. int[] texto = new int[4 * n + 2];
  219.  
  220. int inicioT = 2 * n + 1;
  221.  
  222. for (int i = 0; i < n; i++) {
  223. int simboloS = cadenaS.charAt(i) + 2;
  224. int simboloT = cadenaT.charAt(i) + 2;
  225.  
  226. texto[i] = simboloS;
  227. texto[i + n] = simboloS;
  228.  
  229. texto[inicioT + i] = simboloT;
  230. texto[inicioT + n + i] = simboloT;
  231. }
  232.  
  233. texto[2 * n] = 1;
  234. texto[4 * n + 1] = 0;
  235.  
  236. return texto;
  237. }
  238.  
  239. static long contarPares(
  240. int n,
  241. int[] sufijos,
  242. int[] lcp
  243. ) {
  244. int inicioT = 2 * n + 1;
  245.  
  246. int grupoS = 0;
  247. int grupoT = 0;
  248.  
  249. int anteriorSeleccionado = -1;
  250. int minimoLCP = Integer.MAX_VALUE;
  251.  
  252. long acumuladoS = 0;
  253. long respuesta = 0;
  254.  
  255. for (int i = 0; i < sufijos.length; i++) {
  256.  
  257. if (anteriorSeleccionado != -1) {
  258. minimoLCP = Math.min(minimoLCP, lcp[i]);
  259. }
  260.  
  261. int posicion = sufijos[i];
  262.  
  263. boolean esS = posicion < n;
  264.  
  265. boolean esT =
  266. posicion >= inicioT &&
  267. posicion < inicioT + n;
  268.  
  269. if (!esS && !esT) {
  270. continue;
  271. }
  272.  
  273. if (anteriorSeleccionado == -1 ||
  274. minimoLCP < n) {
  275.  
  276. respuesta += acumuladoS * grupoT;
  277. respuesta += (long) grupoS * grupoT;
  278.  
  279. acumuladoS += grupoS;
  280.  
  281. grupoS = 0;
  282. grupoT = 0;
  283. }
  284.  
  285. if (esS) {
  286. grupoS++;
  287. } else {
  288. grupoT++;
  289. }
  290.  
  291. anteriorSeleccionado = i;
  292. minimoLCP = Integer.MAX_VALUE;
  293. }
  294.  
  295. respuesta += acumuladoS * grupoT;
  296. respuesta += (long) grupoS * grupoT;
  297.  
  298. return respuesta;
  299. }
  300.  
  301. static long resolver(
  302. int n,
  303. String cadenaS,
  304. String cadenaT
  305. ) {
  306. int[] texto = construirTexto(cadenaS, cadenaT, n);
  307.  
  308. int[] sufijos = construirSuffixArray(texto);
  309.  
  310. int[] lcp = construirLCP(texto, sufijos);
  311.  
  312. return contarPares(n, sufijos, lcp);
  313. }
  314.  
  315. public static void main(String[] args) throws IOException {
  316. EntradaRapida lector = new EntradaRapida();
  317.  
  318. int n = lector.leerEntero();
  319.  
  320. if (n == -1) return;
  321.  
  322. String cadenaS = lector.leerCadena();
  323. String cadenaT = lector.leerCadena();
  324.  
  325. if (cadenaS == null || cadenaT == null ||
  326. cadenaS.length() != n || cadenaT.length() != n) {
  327. return;
  328. }
  329.  
  330. System.out.println(resolver(n, cadenaS, cadenaT));
  331. }
  332. }
Success #stdin #stdout 0.08s 16544KB
stdin
Standard input is empty
stdout
Standard output is empty