From c6d997668a2a61fb4068a8eb9737241017d6472a Mon Sep 17 00:00:00 2001 From: Siyong Date: Sun, 19 Jul 2020 17:57:24 -0700 Subject: [PATCH] Problems Started writing conversion in string suffix structs --- content/5_Plat/Centroid.mdx | 46 ++++++++++++++++- content/5_Plat/DP_Bitmasks.mdx | 4 +- content/6_Advanced/String_Suffix.mdx | 75 ++++++++++++++++++++++++++-- 3 files changed, 117 insertions(+), 8 deletions(-) diff --git a/content/5_Plat/Centroid.mdx b/content/5_Plat/Centroid.mdx index ee04b74..ce1ff91 100644 --- a/content/5_Plat/Centroid.mdx +++ b/content/5_Plat/Centroid.mdx @@ -9,12 +9,20 @@ description: "?" frequency: 1 --- + + import { Problem } from "../models"; export const metadata = { problems: { general: [ new Problem("CF", "Ciel the Commander", "problemset/problem/321/C", "Easy", false, ["Centroid"], ""), + new Problem("Plat", "New Barns", "817", "Normal", true, ["Centroid"], ""), new Problem("CF", "Sherlock's bet to Moriarty", "contest/776/problem/F", "Normal", false, ["Centroid"], ""), new Problem("CF", "Digit Tree", "contest/715/problem/C", "Normal", false, ["Centroid", "NT"], ""), new Problem("CF", "Double Tree", "contest/1140/problem/G", "Normal", false, ["Centroid", "DP"], ""), @@ -84,9 +92,43 @@ void centroid(int n = 1) - + - + + +```java +boolean[] r = new boolean[MN];//removed +int[] s = new int[MN];//subtree size +public int dfs(int n, int p) +{ + s[n] = 1; + for(int x : a[n]) + if(x != p && !r[x]) + s[n] += dfs(x, n); + return s[n]; +} +public int get_centroid(int n, int ms, int p)//n = node, ms = size of tree, p = parent +{ + for(int x : a[n]) + if(x != p && !r[x]) + if(s[x]*2 > ms) + return get_centroid(x, ms, n); + return n; +} +public void centroid(int n) +{ + int C = get_centroid(n, dfs(n, 0), 0); + + //do something + + r[C] = 1; + for(int x : a[C]) + if(!r[x]) + centroid(x); +} +``` + + diff --git a/content/5_Plat/DP_Bitmasks.mdx b/content/5_Plat/DP_Bitmasks.mdx index a6be017..2522634 100644 --- a/content/5_Plat/DP_Bitmasks.mdx +++ b/content/5_Plat/DP_Bitmasks.mdx @@ -23,6 +23,7 @@ export const metadata = { new Problem("CSES", "Elevator Rides", "1653", "Normal", false, ["Bitmasks"], ""), new Problem("ojuz", "IZhO Bank", "IZhO14_bank", "Normal", false, ["Bitmasks"], ""), new Problem("YS", "Max Indep Set", "maximum_independent_set", "Normal", false, ["Bitmasks", "Meet in Middle"], ""), + new Problem("CF", "Wise Men", "contest/1326/problem/F2", "Very Hard", false, ["Bitmasks", "DP", "SOS"], "Solve the case where for each binary string s, a 1 means that the adjacent men know each other, and the 0 means nothing: they can know each other or not."), ], broken: [ new Problem("CF", "Guards in the Storehouse", "problemset/problem/845/F", "Normal", false, [], ""), @@ -44,6 +45,7 @@ You can often use this to solve subtasks. + Sum over Subsets DP ## Problems @@ -58,4 +60,4 @@ You can often use this to solve subtasks. (fill in? more probs?) - \ No newline at end of file + diff --git a/content/6_Advanced/String_Suffix.mdx b/content/6_Advanced/String_Suffix.mdx index a4093c6..43971ea 100644 --- a/content/6_Advanced/String_Suffix.mdx +++ b/content/6_Advanced/String_Suffix.mdx @@ -204,7 +204,7 @@ Naively, this would take up $O(N^2)$ memory, but *path compression* enables it t -### Generate Suffix Array +### Generate Suffix Array from Suffix Tree A suffix array can be generated by the suffix tree by taking the dfs traversal of the suffix tree. @@ -217,12 +217,12 @@ A suffix array can be generated by the suffix tree by taking the dfs traversal o ```cpp int N, sa[MN];//length of string, suffix array -struct edge +struct Edge { public: int n, l, r;//node, edge covers s[l..r] explicit operator bool() const {return n!=-1;} -} c[MN*2][26]; +} c[MN*2][26]; // edges of a suffix tree void dfs(int n=0, int d=0) { @@ -239,9 +239,74 @@ void dfs(int n=0, int d=0) ``` - + - +### Generate Suffix Tree from Suffix Array + +Of course, the above operation can be reversed as well. +Each element in the suffix array corresponds to a leaf in the suffix tree. +The LCP array stores information about the Lowest Common Ancestor of two adjacent elements in the suffix array. +Using these two pieces of information, we can construct the suffix tree from the suffix array in linear time. + + + + + +```cpp +//untested +int N, sa[MN], lcp[MN];//length of string, suffix array, lcp array: lcp[i] stores longest common prefix of sa[i] and sa[i+1] + +struct Edge +{ +public: + int n, l, r; //node, edge covers s[l..r] + explicit operator bool() const {return n!=-1;} +} c[MN*2][26]; // edges of suffix tree + +void build_tree() +{ +} +``` + + + + + +### Generate Suffix Tree from Suffix Automaton + +One interesting thing about Suffix Trees and Suffix Automata is that the link tree of a Suffix Automaton is equivalent to the Suffix Tree of the reversed string. +Since Suffix Automata are much easier to create than Suffix Trees, we can use this as an alternate method to build a Suffix Tree, all in linear time too! + + + + + + + +```cpp +char s[MN]; //string +int ord[MN]; // nodes representing prefixes of the string s +int u[MN*2]; // whether the node has already been created +int l[MN*2]; // link in suffix automaton +Edge c[MN*2][27]; // edge of suffix tree (not automaton; structure of automaton is not necessary to build stree) +void build_tree() +{ + s[N] = 26; // terminator + for(int i=N;i>=0;--i) ord[i]=append(ord[i+1], s[i]); + for(int i=0,x,r,l;i<=N;++i) + { + x=ord[i], r=N+1; + for(;x&&!u[x];x=l[x]) + { + l=r-d[x]+d[l[x]]; + c[l[x]][s[l]]={x, l, r}; + r=l; + u[x]=1; + } + } +} +``` +