fork download
  1.  
  2. import java.io.*;
  3. import java.util.*;
  4.  
  5. public class Main {
  6.  
  7. static class Lector {
  8. private final BufferedInputStream entrada =
  9.  
  10. private final byte[] datos = new byte[65536];
  11. private int actual = 0;
  12. private int disponible = 0;
  13.  
  14. private int obtener() throws IOException {
  15. if (actual == disponible) {
  16. disponible = entrada.read(datos);
  17. actual = 0;
  18.  
  19. if (disponible == -1) return -1;
  20. }
  21.  
  22. return datos[actual++];
  23. }
  24.  
  25. int entero() throws IOException {
  26. int c;
  27.  
  28. do {
  29. c = obtener();
  30. if (c == -1) return -1;
  31. } while (c <= 32);
  32.  
  33. int valor = 0;
  34.  
  35. while (c > 32) {
  36. valor = valor * 10 + c - 48;
  37. c = obtener();
  38. }
  39.  
  40. return valor;
  41. }
  42.  
  43. String cadena() throws IOException {
  44. StringBuilder sb = new StringBuilder();
  45. int c;
  46.  
  47. do {
  48. c = obtener();
  49. if (c == -1) return null;
  50. } while (c <= 32);
  51.  
  52. while (c > 32) {
  53. sb.append((char) c);
  54. c = obtener();
  55. }
  56.  
  57. return sb.toString();
  58. }
  59. }
  60.  
  61. static int[] crearOrden(int[] datos) {
  62. int n = datos.length;
  63.  
  64. int[] orden = new int[n];
  65. int[] clase = new int[n];
  66. int[] temporal = new int[n];
  67. int[] siguienteClase = new int[n];
  68.  
  69. int mayor = 0;
  70.  
  71. for (int x : datos) {
  72. if (x > mayor) mayor = x;
  73. }
  74.  
  75. int[] cuenta = new int[Math.max(n, mayor + 1)];
  76.  
  77. for (int x : datos) {
  78. cuenta[x]++;
  79. }
  80.  
  81. for (int i = 1; i <= mayor; i++) {
  82. cuenta[i] += cuenta[i - 1];
  83. }
  84.  
  85. for (int i = n - 1; i >= 0; i--) {
  86. orden[--cuenta[datos[i]]] = i;
  87. }
  88.  
  89. int grupos = 1;
  90. clase[orden[0]] = 0;
  91.  
  92. for (int i = 1; i < n; i++) {
  93. if (datos[orden[i]] != datos[orden[i - 1]]) {
  94. grupos++;
  95. }
  96.  
  97. clase[orden[i]] = grupos - 1;
  98. }
  99.  
  100. for (int salto = 1; salto < n; salto <<= 1) {
  101.  
  102. for (int i = 0; i < n; i++) {
  103. int p = orden[i] - salto;
  104. temporal[i] = p < 0 ? p + n : p;
  105. }
  106.  
  107. Arrays.fill(cuenta, 0, grupos, 0);
  108.  
  109. for (int i = 0; i < n; i++) {
  110. cuenta[clase[temporal[i]]]++;
  111. }
  112.  
  113. for (int i = 1; i < grupos; i++) {
  114. cuenta[i] += cuenta[i - 1];
  115. }
  116.  
  117. for (int i = n - 1; i >= 0; i--) {
  118. int p = temporal[i];
  119. orden[--cuenta[clase[p]]] = p;
  120. }
  121.  
  122. siguienteClase[orden[0]] = 0;
  123.  
  124. int nuevosGrupos = 1;
  125.  
  126. for (int i = 1; i < n; i++) {
  127. int a = orden[i];
  128. int b = orden[i - 1];
  129.  
  130. int a2 = a + salto;
  131. int b2 = b + salto;
  132.  
  133. if (a2 >= n) a2 -= n;
  134. if (b2 >= n) b2 -= n;
  135.  
  136. if (clase[a] != clase[b] ||
  137. clase[a2] != clase[b2]) {
  138. nuevosGrupos++;
  139. }
  140.  
  141. siguienteClase[a] = nuevosGrupos - 1;
  142. }
  143.  
  144. int[] cambio = clase;
  145. clase = siguienteClase;
  146. siguienteClase = cambio;
  147.  
  148. grupos = nuevosGrupos;
  149.  
  150. if (grupos == n) break;
  151. }
  152.  
  153. return orden;
  154. }
  155.  
  156. static int[] obtenerLCP(int[] datos, int[] orden) {
  157. int n = datos.length;
  158.  
  159. int[] rango = new int[n];
  160. int[] comun = new int[n];
  161.  
  162. for (int i = 0; i < n; i++) {
  163. rango[orden[i]] = i;
  164. }
  165.  
  166. int k = 0;
  167.  
  168. for (int i = 0; i < n; i++) {
  169. int posicion = rango[i];
  170.  
  171. if (posicion == 0) {
  172. k = 0;
  173. continue;
  174. }
  175.  
  176. int anterior = orden[posicion - 1];
  177.  
  178. while (i + k < n &&
  179. anterior + k < n &&
  180. datos[i + k] == datos[anterior + k]) {
  181. k++;
  182. }
  183.  
  184. comun[posicion] = k;
  185.  
  186. if (k > 0) k--;
  187. }
  188.  
  189. return comun;
  190. }
  191.  
  192. static int[] unirCadenas(String s, String t, int n) {
  193. int[] resultado = new int[4 * n + 2];
  194.  
  195. int baseT = 2 * n + 1;
  196.  
  197. for (int i = 0; i < n; i++) {
  198. int x = s.charAt(i) + 2;
  199. int y = t.charAt(i) + 2;
  200.  
  201. resultado[i] = x;
  202. resultado[i + n] = x;
  203.  
  204. resultado[baseT + i] = y;
  205. resultado[baseT + n + i] = y;
  206. }
  207.  
  208. resultado[2 * n] = 1;
  209. resultado[4 * n + 1] = 0;
  210.  
  211. return resultado;
  212. }
  213.  
  214. static long calcularRespuesta(
  215. int n,
  216. int[] orden,
  217. int[] comun
  218. ) {
  219. int baseT = 2 * n + 1;
  220.  
  221. int cantidadS = 0;
  222. int cantidadT = 0;
  223.  
  224. int ultimo = -1;
  225. int minimo = Integer.MAX_VALUE;
  226.  
  227. long anterioresS = 0;
  228. long resultado = 0;
  229.  
  230. for (int i = 0; i < orden.length; i++) {
  231.  
  232. if (ultimo != -1) {
  233. minimo = Math.min(minimo, comun[i]);
  234. }
  235.  
  236. int p = orden[i];
  237.  
  238. boolean perteneceS = p < n;
  239.  
  240. boolean perteneceT =
  241. p >= baseT && p < baseT + n;
  242.  
  243. if (!perteneceS && !perteneceT) {
  244. continue;
  245. }
  246.  
  247. if (ultimo == -1 || minimo < n) {
  248.  
  249. resultado += anterioresS * cantidadT;
  250. resultado += (long) cantidadS * cantidadT;
  251.  
  252. anterioresS += cantidadS;
  253.  
  254. cantidadS = 0;
  255. cantidadT = 0;
  256. }
  257.  
  258. if (perteneceS) {
  259. cantidadS++;
  260. } else {
  261. cantidadT++;
  262. }
  263.  
  264. ultimo = i;
  265. minimo = Integer.MAX_VALUE;
  266. }
  267.  
  268. resultado += anterioresS * cantidadT;
  269. resultado += (long) cantidadS * cantidadT;
  270.  
  271. return resultado;
  272. }
  273.  
  274. static long ejecutar(int n, String s, String t) {
  275. int[] texto = unirCadenas(s, t, n);
  276.  
  277. int[] orden = crearOrden(texto);
  278.  
  279. int[] comun = obtenerLCP(texto, orden);
  280.  
  281. return calcularRespuesta(n, orden, comun);
  282. }
  283.  
  284. public static void main(String[] args) throws IOException {
  285. Lector entrada = new Lector();
  286.  
  287. int n = entrada.entero();
  288.  
  289. if (n < 1) return;
  290.  
  291. String s = entrada.cadena();
  292. String t = entrada.cadena();
  293.  
  294. if (s == null || t == null ||
  295. s.length() != n || t.length() != n) {
  296. return;
  297. }
  298.  
  299. System.out.println(ejecutar(n, s, t));
  300. }
  301. }
Success #stdin #stdout 0.08s 52772KB
stdin
Standard input is empty
stdout
Standard output is empty