Advertisement
Guest User

LCP on a Tree

a guest
Dec 21st, 2016
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
D 10.03 KB | None | 0 0
  1. import core.bitop;
  2. import core.checkedint;
  3. import core.simd;
  4. import core.stdc.stdio;
  5. import core.stdc.stdlib;
  6. import core.stdc.string;
  7. import std.algorithm;
  8. import std.array;
  9. import std.ascii;
  10. import std.bigint;
  11. import std.bitmanip;
  12. import std.complex;
  13. import std.container;
  14. import std.conv;
  15. import std.datetime;
  16. import std.format;
  17. import std.functional;
  18. import std.math;
  19. import std.meta;
  20. import std.numeric;
  21. import std.random;
  22. import std.range;
  23. import std.regex;
  24. import std.string;
  25. import std.typecons;
  26. import std.variant;
  27.  
  28. __gshared:
  29.  
  30. bool read(T...)(T ptrs) if (ptrs.length > 0) {
  31.     return readf(' ' ~ replicate("%s ", ptrs.length), ptrs) == ptrs.length;
  32. }
  33.  
  34. T[ ] allocate(T)(size_t n) {
  35.     return (cast(T*)malloc(n * T.sizeof))[0 .. n];
  36. }
  37.  
  38. auto pairwise(R)(R range) if (isForwardRange!R) {
  39.     return lockstep(range, dropOne(range));
  40. }
  41.  
  42. struct Lca(Node, int n, Flag!`checkBackReferences` checkBackReferences = No.checkBackReferences,
  43.         Flag!`assignLineIndices` assignLineIndices = No.assignLineIndices) {
  44.     Node*[n + 1] lp;
  45.     int[n + 1] height;
  46.  
  47.     static if (assignLineIndices)
  48.         int[n + 1] lineSize;
  49.  
  50.     void init(Node* root) {
  51.         int gid = 1;
  52.  
  53.         static if (checkBackReferences)
  54.             alias DfsArgs = AliasSeq!(Node*, const Node*);
  55.         else
  56.             alias DfsArgs = AliasSeq!(Node*);
  57.  
  58.         int dfs0(DfsArgs args) {
  59.             with (args[0]) {
  60.                 id = deepestId = gid++;
  61.                 static if (assignLineIndices)
  62.                     lineSize[deepestId] = 0;
  63.                 int h = bsf(id);
  64.                 foreach (node; adj) {
  65.                     static if (checkBackReferences) {
  66.                         if (node is args[1])
  67.                             continue;
  68.                         const t = dfs0(node, args[0]);
  69.                     } else
  70.                         const t = dfs0(node);
  71.                     if (t > h) {
  72.                         h = t;
  73.                         deepestId = node.deepestId;
  74.                     }
  75.                     lp[node.deepestId] = args[0];
  76.                 }
  77.                 height[id] = h;
  78.                 return h;
  79.             }
  80.         }
  81.  
  82.         void dfs1(DfsArgs args) {
  83.             with (args[0]) {
  84.                 static if (assignLineIndices)
  85.                     indexInLine = lineSize[deepestId]++;
  86.                 mask |= deepestId & -deepestId;
  87.                 foreach (node; adj)
  88.                     static if (checkBackReferences) {
  89.                         if (node !is args[1]) {
  90.                             node.mask = mask;
  91.                             dfs1(node, args[0]);
  92.                         }
  93.                     } else {
  94.                         node.mask = mask;
  95.                         dfs1(node);
  96.                     }
  97.             }
  98.         }
  99.  
  100.         root.mask = 0x0;
  101.         static if (checkBackReferences) {
  102.             dfs0(root, null);
  103.             dfs1(root, null);
  104.         } else {
  105.             dfs0(root);
  106.             dfs1(root);
  107.         }
  108.     }
  109.  
  110.     Node* get(Node* x, Node* y) {
  111.         const dpx = x.deepestId, dpy = y.deepestId;
  112.         if (dpx != dpy) {
  113.             const k = bsr(dpx ^ dpy);
  114.             const zh = bsf(x.mask & y.mask & ~0 << height[(dpx >> k | 0x1) << k]);
  115.  
  116.             Node* raise(int deepestId, int mask) {
  117.                 const k = bsr(mask & ((1 << zh) - 1));
  118.                 return lp[(deepestId >> k | 0x1) << k];
  119.             }
  120.  
  121.             if (bsf(x.mask) != zh)
  122.                 x = raise(dpx, x.mask);
  123.             if (bsf(y.mask) != zh)
  124.                 y = raise(dpy, y.mask);
  125.         }
  126.         return x.id < y.id? x : y;
  127.     }
  128. }
  129.  
  130. struct AutoNode {
  131.     int len;
  132.     AutoNode*[char] next;
  133.     AutoNode* link;
  134.     AutoNode*[ ] invLinks;
  135.     int id, deepestId, mask;
  136.  
  137.     alias adj = invLinks;
  138.  
  139.     AutoNode* append(char c, AutoNode* last) {
  140.         auto cur = createNode(AutoNode(last.len + 1));
  141.         AutoNode** p;
  142.         while ((p = c in last.next) is null) {
  143.             last.next[c] = cur;
  144.             last = last.link;
  145.             if (last is null) {
  146.                 cur.link = &this;
  147.                 return cur;
  148.             }
  149.         }
  150.         auto q = *p;
  151.         if (q.len == last.len + 1) {
  152.             cur.link = q;
  153.             return cur;
  154.         }
  155.         auto clone = createNode(*q);
  156.         clone.len = last.len + 1;
  157.         cur.link = q.link = clone;
  158.         do {
  159.             *p = clone;
  160.             last = last.link;
  161.             if (last is null)
  162.                 break;
  163.             p = c in last.next;
  164.         } while (p !is null && *p == q);
  165.         return cur;
  166.     }
  167. }
  168.  
  169. struct TreeNode {
  170.     char c;
  171.     TreeNode*[ ] adj;
  172.     int id, deepestId, mask, indexInLine, indexInString;
  173.  
  174.     void genString(in TreeNode* prev) {
  175.         indexInString = strSize;
  176.         str[strSize++] = c;
  177.         foreach (node; adj)
  178.             if (node !is prev && node.deepestId == deepestId) {
  179.                 node.genString(&this);
  180.                 break;
  181.             }
  182.         foreach (node; adj)
  183.             if (node !is prev && node.deepestId != deepestId)
  184.                 node.genString(&this);
  185.     }
  186. }
  187.  
  188. struct Waypoint {
  189.     int pos, lpos, trgLpos;
  190.     bool up;
  191. }
  192.  
  193. int n;
  194. TreeNode[300_000] _nodes;
  195. int strSize;
  196. char[300_000] str;
  197. int auNodesSize;
  198. AutoNode[ ] auNodes;
  199. AutoNode*[300_000] _tdNodes, _buNodes;
  200. AutoNode*[ ] tdNodes, buNodes;
  201. Lca!(TreeNode, 300_000, Yes.checkBackReferences, Yes.assignLineIndices) treeLca;
  202. Lca!(AutoNode, 1_200_000) auLca;
  203. Waypoint[38][2] wp;
  204.  
  205. auto createNode()(auto ref AutoNode node) {
  206.     auNodes[auNodesSize] = node;
  207.     return &auNodes[auNodesSize++];
  208. }
  209.  
  210. int solve(TreeNode* a, TreeNode* b, TreeNode* c, TreeNode* d) {
  211.     auto calcWaypoints(const(TreeNode)* a, const(TreeNode)* b, Waypoint[ ] wp) {
  212.         const lca = treeLca.get(a, b);
  213.         int i = 0;
  214.  
  215.         void walkUp(const(TreeNode)* node, bool up) {
  216.             while (node.deepestId != lca.deepestId) {
  217.                 wp[i++] = Waypoint(node.indexInString, node.indexInLine, 0, up);
  218.                 node = treeLca.lp[node.deepestId];
  219.             }
  220.             if (up)
  221.                 wp[i++] = Waypoint(node.indexInString, node.indexInLine, lca.indexInLine, up);
  222.         }
  223.  
  224.         walkUp(a, true);
  225.         const mid = i;
  226.         walkUp(b, false);
  227.         wp[mid .. i].reverse();
  228.         return wp[0 .. i];
  229.     }
  230.  
  231.     auto wp0 = calcWaypoints(a, b, wp[0][ ]);
  232.     auto wp1 = calcWaypoints(c, d, wp[1][ ]);
  233.     int result = 0;
  234.     while (!wp0.empty && !wp1.empty) {
  235.         a = wp0.front;
  236.         c = wp1.front;
  237.         auto node0 = a.up? buNodes[a.pos] : tdNodes[a.pos - a.lpos];
  238.         auto node1 = c.up? buNodes[c.pos] : tdNodes[c.pos - c.lpos];
  239.         const aLim = a.lpos - a.trgLpos + 1;
  240.         const cLim = c.lpos - c.trgLpos + 1;
  241.         const lce = min(auLca.get(node0, node1).len, aLim, cLim);
  242.  
  243.     }
  244.  
  245.     /+
  246.     static struct NodeInfo {
  247.         int pos, lpos, dpi;
  248.     }
  249.  
  250.     bool up1 = c != lca1;
  251.     NodeInfo ai = { a.indexInString, a.indexInLine, a.deepestId };
  252.     NodeInfo ci = { c.indexInString, c.indexInLine, c.deepestId };
  253.  
  254.     void raise(ref NodeInfo i) {
  255.         auto node = treeLca.lp[i.dpi];
  256.         i.pos = node.indexInString;
  257.         i.lpos = node.indexInLine;
  258.         i.dpi = node.deepestId;
  259.     }
  260.  
  261.     void shiftUp(ref NodeInfo i, int offset) {
  262.         assert(i.pos >= offset);
  263.         assert(i.lpos >= offset);
  264.         i.pos -= offset;
  265.         i.lpos -= offset;
  266.     }
  267.  
  268.     while (ai.pos != lca0.indexInString) {
  269.         if (ai.dpi != lca0.deepestId) {
  270.             if (up1) {
  271.                 if (ci.dpi != lca1.deepestId) {
  272.                     //The simplest case: just go up.
  273.                     const aLim = ai.lpos + 1, cLim = ci.lpos + 1;
  274.                     const lce = min(auLca.get(buNodes[ai.pos], buNodes[ci.pos]).len, aLim, cLim);
  275.                     result += lce;
  276.                     if (lce < aLim && lce < cLim)
  277.                         return result;
  278.                     if (lce == aLim) {
  279.                         raise(ai);
  280.                         if (lce == cLim)
  281.                             raise(ci);
  282.                         else
  283.                             shiftUp(ci, lce);
  284.                     } else {
  285.                         raise(ci);
  286.                         shiftUp(ai, lce);
  287.                     }
  288.                 } else {
  289.                     //c lays in the same line as lca1.
  290.                     const lce = min(
  291.                         auLca.get(buNodes[ai.pos], buNodes[ci.pos]).len,
  292.                         ai.lpos + 1,
  293.                         ci.lpos - lca1.lpos + 1,
  294.                     );
  295.                     result += lce;
  296.                 }
  297.             }
  298.         }
  299.     }
  300.     +/
  301.  
  302.     return result;
  303. }
  304.  
  305. void main() {
  306.     auNodes = allocate!AutoNode(1_200_000);
  307.     while (scanf("%d ", &n) == 1) {
  308.         auto nodes = _nodes[0 .. n];
  309.         foreach (ref node; nodes)
  310.             node.c = cast(char)getchar();
  311.         foreach (i; 1 .. n) {
  312.             int a, b;
  313.             scanf("%d%d", &a, &b);
  314.             a--;
  315.             b--;
  316.             nodes[a].adj ~= &nodes[b];
  317.             nodes[b].adj ~= &nodes[a];
  318.         }
  319.  
  320.         treeLca.init(&nodes[0]);
  321.         strSize = 0;
  322.         nodes[0].genString(null);
  323.         assert(strSize == n);
  324.  
  325.         AutoNode root;
  326.         tdNodes = _tdNodes[0 .. n];
  327.         buNodes = _buNodes[0 .. n];
  328.         auNodesSize = 0;
  329.         //Build automata on reversed strings.
  330.         auto last = &root;
  331.         foreach_reverse (i, c; str[0 .. n])
  332.             last = tdNodes[i] = root.append(c, last);
  333.         foreach (i, c; str[0 .. n])
  334.             last = buNodes[i] = root.append(c, last);
  335.         foreach (ref node; auNodes[0 .. auNodesSize])
  336.             node.link.invLinks ~= &node;
  337.         auLca.init(&root);
  338.  
  339.         int q;
  340.         scanf("%d", &q);
  341.         while (q--) {
  342.             int a, b, c, d;
  343.             scanf("%d%d%d%d", &a, &b, &c, &d);
  344.             printf("%d\n", solve(&nodes[a - 1], &nodes[b - 1], &nodes[c - 1], &nodes[d - 1]));
  345.         }
  346.     }
  347. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement