You are viewing a single comment's thread. Return to all comments →
//Solution In Java
import java.math.*; import java.util.*; public class S implements Runnable { static Random R = new Random(7777L); static int M = 100000, A = 26, H = BigInteger.probablePrime(17, R).intValue(); static int[] P = new int[M * 2]; static { P[0] = 1; for (int i = 1; i < P.length; i++) P[i] = P[i - 1] * H; } char[] s; int n; int[][] cm, cp, dh; int[] hp; void solve() throws IOException { s = new StringBuilder(in.readLine()).reverse().toString().toCharArray(); n = s.length; cm = gcm(s); cp = gcp(cm); dh = gdh(s); hp = php(cp, dh); Integer[] sa = gsa(); final int[] si = new int[n]; for (int i = 0; i < n; i++) si[sa[i]] = i; NavigableSet<Integer> v = new TreeSet<>((p1, p2) -> si[p1] - si[p2]); long[] c = new long[n + 1]; for (int p = n - 1; p >= 0; p--) { long is = 0; Integer np = v.lower(p); if (np != null) is = Math.max(is, lcp(p, np)); np = v.higher(p); if (np != null) is = Math.max(is, lcp(p, np)); c[p] = c[p + 1] + n - p - is; v.add(p); } for (int i = 0; i < n; i++) out.println(c[n - 1 - i]); } Integer[] gsa() { Integer[] sa = new Integer[n]; for (int i = 0; i < n; i++) sa[i] = i; Arrays.sort(sa, (p1, p2) -> { if (p1.equals(p2)) return 0; int l = lcp(p1, p2); if (l == n - p1) return -1; if (l == n - p2) return 1; return cm[p1][s[p1 + l] - 'a'] - cm[p2][s[p2 + l] - 'a']; }); return sa; } int lcp(int p1, int p2) { if (p1 > p2) return lcp(p2, p1); int rb = n - p2; int l = nl(p1, p2, Math.min(120, rb)); int lb = 0; if (l == -1) { lb = Math.min(15, rb); while (lb <= rb) { int m = (lb + rb) >> 1; if (eq(p1, p2, m)) { l = Math.max(l, m); lb = m + 1; } else rb = m - 1; } } return l; } int nl(int p1, int p2, int len) { int[] m1 = cm[p1], m2 = cm[p2]; for (int i = 0; i < len; i++) if (m1[s[p1 + i] - 'a'] != m2[s[p2 + i] - 'a']) return i; return -1; } boolean eq(int p1, int p2, int len) { if (p1 > p2) return eq(p2, p1, len); int h1 = h(p1, len); int h2 = h(p2, len); return P[p2 - p1] * h1 == h2; } int h(int p, int len) { int[] pr = cp[p]; int[] hs = dh[p + len]; int ha = -hp[p]; for (int r = 0; r < pr.length; r++) ha += hs[pr[r]] * r; return ha; } static int[][] gcm(char[] s) { int n = s.length; int[][] ltn = gln(s); int[][] m = new int[n][A]; for (int o = 0; o < n; o++) { int[] mp = m[o]; Arrays.fill(mp, -1); int md = 0; mp[s[o] - 'a'] = md++; for (int pos = o; pos < n; ) { int np = n; int nc = -1; for (int ch = 0; ch < A; ch++) if (mp[ch] == -1) if (np > ltn[pos][ch]) { np = ltn[pos][ch]; nc = ch; } if (nc == -1) break; mp[nc] = md++; pos = np; } } return m; } static int[][] gln(char[] s) { int n = s.length; int[][] l = new int[n][A]; for (int[] r : l) Arrays.fill(r, n); for (int i = n - 2; i >= 0; i--) { System.arraycopy(l[i + 1], 0, l[i], 0, A); l[i][s[i + 1] - 'a'] = i + 1; } return l; } static int[][] gdh(char[] s) { int n = s.length; int[][] d = new int[n + 1][A]; for (int i = 0; i < n; i++) { System.arraycopy(d[i], 0, d[i + 1], 0, A); d[i + 1][s[i] - 'a'] += P[i]; } return d; } static int[][] gcp(int[][] cm) { int n = cm.length; int[][] c = new int[n][]; for (int p = 0; p < n; p++) c[p] = gc(cm[p]); return c; } static int[] gc(int[] m) { int[] p = new int[A]; int la = 0; for (int ch = 0; ch < A; ch++) if (m[ch] != -1) { p[m[ch]] = ch; la = Math.max(la, m[ch]); } return Arrays.copyOf(p, la + 1); } static int[] php(int[][] cp, int[][] dh) { int n = cp.length; int[] h = new int[n]; for (int p = 0; p < n; p++) { int[] hs = dh[p]; int[] pr = cp[p]; for (int r = 0; r < pr.length; r++) h[p] += hs[pr[r]] * r; } return h; } static S I = new S(); public static void main(String[] a) { I.run(); } public void run() { try { in = new BufferedReader(new InputStreamReader(System.in)); out = new PrintWriter(System.out); solve(); out.close(); } catch (Throwable e) { e.printStackTrace(); System.exit(999); } } BufferedReader in; PrintWriter out; }
Seems like cookies are disabled on this browser, please enable them to open this website
Pseudo-Isomorphic Substrings
You are viewing a single comment's thread. Return to all comments →
//Solution In Java