Advertisement
Guest User

Untitled

a guest
Mar 26th, 2018
342
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 6.14 KB | None | 0 0
  1. import java.util.*;
  2.  
  3.  
  4. public class b {
  5.     static int next[][] = new int[26][26];
  6.     static int tot[] = new int[27];
  7.     static int cost[][] = new int[26][26];
  8.     static int best[] = new int[1 << 26];
  9.     static int reMap[] = new int[26];
  10.     static int cheapest = Integer.MAX_VALUE;
  11.     static long count[] = new long[4];
  12.     static int idx = 0, components = 26;
  13.     static long factorials[][];
  14.     static final long mod[] = { (long) 1e9 + 7, (long) 1e9 + 9, (long) 1e9 + 21, (long) 1e9 + 33 };
  15.     static int done;
  16.     static HashMap<Long, Integer> states = new HashMap<>();
  17.    
  18.     static class Hungarian {
  19.         static int inf = 100000000;
  20.         int[][] c;
  21.         int[] lx, ly, xy, yx, s, sx, p, q;
  22.         int n, m;
  23.         boolean[] S, T;
  24.  
  25.         public Hungarian(int[][] cost) {
  26.             c = cost;
  27.             n = c.length;
  28.             m = c[0].length;
  29.             S = new boolean[n];
  30.             T = new boolean[m];
  31.             lx = new int[n];
  32.             ly = new int[m];
  33.             xy = new int[n];
  34.             yx = new int[m];
  35.             s = new int[m];
  36.             sx = new int[m];
  37.             p = new int[n];
  38.             q = new int[n];
  39.         }
  40.  
  41.         void augment() {
  42.             int x, y, root = -1, wr = 0, rd = 0;
  43.             Arrays.fill(S, false);
  44.             Arrays.fill(T, false);
  45.             for (x = 0; x < n; x++) {
  46.                 if (xy[x] == -1) {
  47.                     q[wr++] = root = x;
  48.                     p[x] = -2;
  49.                     S[x] = true;
  50.                     break;
  51.                 }
  52.             }
  53.             for (y = 0; y < m; y++) {
  54.                 s[y] = lx[root] + ly[y] - c[root][y];
  55.                 sx[y] = root;
  56.             }
  57.             while (y >= m) {
  58.                 while (rd < wr && y >= m) {
  59.                     x = q[rd++];
  60.                     for (y = 0; y < m; y++) {
  61.                         if (c[x][y] == lx[x] + ly[y] && !T[y]) {
  62.                             if (yx[y] == -1)
  63.                                 break;
  64.                             T[y] = true;
  65.                             q[wr++] = yx[y];
  66.                             addToTree(yx[y], x);
  67.                         }
  68.                     }
  69.                 }
  70.                 if (y < m)
  71.                     break;
  72.                 updateLabels();
  73.                 wr = rd = 0;
  74.                 for (y = 0; y < m; y++) {
  75.                     if (!T[y] && s[y] == 0) {
  76.                         if (yx[y] == -1) {
  77.                             x = sx[y];
  78.                             break;
  79.                         } else {
  80.                             T[y] = true;
  81.                             if (!S[yx[y]]) {
  82.                                 q[wr++] = yx[y];
  83.                                 addToTree(yx[y], sx[y]);
  84.                             }
  85.                         }
  86.                     }
  87.  
  88.                 }
  89.             }
  90.             for (int cx = x, cy = y, ty; cx != -2; cx = p[cx], cy = ty) {
  91.                 ty = xy[cx];
  92.                 yx[cy] = cx;
  93.                 xy[cx] = cy;
  94.             }
  95.         }
  96.  
  97.         void updateLabels() {
  98.             int x, y, delta = inf;
  99.             for (y = 0; y < m; y++)
  100.                 delta = Math.min(delta, !T[y] ? s[y] : inf);
  101.             for (x = 0; x < n; x++)
  102.                 lx[x] -= S[x] ? delta : 0;
  103.             for (y = 0; y < m; y++) {
  104.                 ly[y] += T[y] ? delta : 0;
  105.                 s[y] -= !T[y] ? delta : 0;
  106.             }
  107.         }
  108.  
  109.         void addToTree(int x, int prevX) {
  110.             S[x] = true;
  111.             p[x] = prevX;
  112.             for (int y = 0; y < m; y++) {
  113.                 if (lx[x] + ly[y] - c[x][y] < s[y]) {
  114.                     s[y] = lx[x] + ly[y] - c[x][y];
  115.                     sx[y] = x;
  116.                 }
  117.             }
  118.         }
  119.  
  120.         int run() {
  121.             Arrays.fill(xy, -1);
  122.             Arrays.fill(yx, -1);
  123.             for (int x = 0; x < n; x++)
  124.                 for (int y = 0; y < m; y++)
  125.                     lx[x] = Math.max(lx[x], c[x][y]);
  126.             for (int i = 0; i < n; i++)
  127.                 augment();
  128.             int ret = 0;
  129.             for (int x = 0; x < n; x++)
  130.                 ret += c[x][xy[x]];
  131.             return ret;
  132.         }
  133.     }
  134.     static int bestCase(int bm) {
  135.         if (best[bm] != -1)
  136.             return best[bm];
  137.  
  138.         int n = idx - Integer.bitCount(bm);
  139.         if (n < 1)
  140.             return 0;
  141.         int cost[][] = new int[n][n];
  142.         int rmap[] = new int[n];
  143.         int c = 0;
  144.         for (int i = 0; i < idx; i++) {
  145.             if ((bm & (1 << i)) == 0) {
  146.                 rmap[c++] = i;
  147.             }
  148.         }
  149.  
  150.         for (int i = 0; i < n; i++) {
  151.             int v = reMap[rmap[i]];
  152.             for (int j = 0; j < n; j++) {
  153.                 int w = reMap[rmap[j]];
  154.                 if (i == j)
  155.                     cost[i][j] = -tot[v];
  156.                 else
  157.                     cost[i][j] = -(tot[v] - next[v][w]);
  158.             }
  159.         }
  160.         Hungarian h = new Hungarian(cost);
  161.         return best[bm] = -h.run();
  162.  
  163.     }
  164.     static long getState(long bm, long last, long letter) {
  165.         return bm | (last << 30) | (letter << 40);
  166.     }
  167.  
  168.    
  169.  
  170.     public static int go(int bm, int last, int cost, int letter) {
  171.         if (bm == done) {
  172.             cost += tot[last];
  173.  
  174.             if (cheapest == cost) {
  175.                 for (int i = 0; i < 4; i++) {
  176.                     count[i] += factorials[i][components];
  177.                     if (count[i] >= mod[i])
  178.                         count[i] -= mod[i];
  179.                 }
  180.             } else if (cheapest > cost) {
  181.                 cheapest = cost;
  182.                 for (int i = 0; i < 4; i++) {
  183.                     count[i] = factorials[i][components];
  184.                 }
  185.             }
  186.             return tot[last];
  187.         }
  188.         long st = getState(bm, last, letter);
  189.         Integer vals = states.get(st);
  190.         if (vals != null) {
  191.             if (vals + cost > cheapest) {
  192.                 return vals;
  193.             }
  194.  
  195.         }
  196.         int ans = 100;
  197.         int bc = 0;
  198.         if (vals == null) {
  199.             if (last != 26) {
  200.                 bc = tot[last];
  201.                 for (int i = 0; i < idx; i++) {
  202.                     if ((bm & (1 << i)) == 0) {
  203.                         int ri = reMap[i];
  204.                         bc = Math.min(bc, tot[last] - next[last][ri]);
  205.                     }
  206.                 }
  207.             }
  208.             if (cost + bestCase(bm) + bc > cheapest)
  209.                 return bestCase(bm) + bc;
  210.         }
  211.         if (last == 26) {
  212.             for (int i = 0; i < idx; i++) {
  213.                 int ri = reMap[i];
  214.                 if ((bm & (1 << i)) == 0) {
  215.                     ans = Math.min(go(bm | (1 << i), ri, cost, ri + 1), ans);
  216.                 }
  217.             }
  218.             return ans;
  219.         }
  220.  
  221.         for (int i = 0; i < idx; i++) { // check the min here
  222.             int ri = reMap[i];
  223.             if ((bm & (1 << i)) == 0) {
  224.                 if (next[last][ri] != 0) {
  225.                     components--;
  226.                     ans = Math.min(ans, go(bm | (1 << i), ri, cost + (tot[last] - next[last][ri]), letter) + tot[last]- next[last][ri]);
  227.                     components++;
  228.                 } else if (next[last][ri] == 0 && ri >= letter) {
  229.                     ans = Math.min(ans, go(bm | (1 << i), ri, cost + tot[last], ri + 1) + tot[last]);
  230.                 }
  231.             }
  232.         }
  233.         states.put(st, ans);
  234.         return ans;
  235.     }
  236.  
  237.  
  238.     public static void main(String[] args) {
  239.         Scanner in = new Scanner(System.in);
  240.         String s = in.next();
  241.         Arrays.fill(best, -1);
  242.         for (int i = 0; i < s.length() - 1; i++) {
  243.             next[s.charAt(i) - 'A'][s.charAt(i + 1) - 'A']++;
  244.             tot[s.charAt(i) - 'A']++;
  245.         }
  246.  
  247.         Arrays.fill(reMap, -1);
  248.         for (int i = 0; i < 26; i++) {
  249.             for (char c : s.toCharArray()) {
  250.                 if (c == 'A' + i) {
  251.                     reMap[idx++] = i;
  252.                     break;
  253.                 }
  254.             }
  255.         }
  256.         for (int i = 0; i < 26; i++)
  257.             next[i][i] = 0;
  258.         factorials = new long[4][30];
  259.         for (int j = 0; j < 4; j++) {
  260.             factorials[j][0] = 1l;
  261.             for (int i = 1; i < 30; i++) {
  262.                 factorials[j][i] = factorials[j][i - 1] * i;
  263.                 factorials[j][i] %= mod[j];
  264.             }
  265.         }
  266.         done = (1 << idx) - 1;
  267.  
  268.         go(0, 26, 0, 0);
  269.  
  270.         for (int j = 0; j < 4; j++)
  271.             System.out.print(count[j] + " ");
  272.  
  273.     }
  274.  
  275. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement