Started writing conversion in string suffix structs
This commit is contained in:
Siyong 2020-07-19 17:57:24 -07:00
parent b125a0be0f
commit c6d997668a
3 changed files with 117 additions and 8 deletions

View file

@ -9,12 +9,20 @@ description: "?"
frequency: 1
---
<!--
TODO:
- Add more resources
-->
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)
</CPPSection>
<JavaSection />
<JavaSection>
<PySection />
<!-- Modified from above. I can't guarauntee it compiles and functions as expected -->
```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);
}
```
</JavaSection>
</LanguageSection>

View file

@ -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.
<Resource source="CPH" title="10 (Bit Manipulation), 19.2 (Hamiltonian Paths)"> </Resource>
<Resource source="CF" title="DP Over Subsets" url="blog/entry/337"> </Resource>
<Resource source="HE" title="DP and Bit Masking" url="https://www.hackerearth.com/practice/algorithms/dynamic-programming/bit-masking/tutorial/"> </Resource>
<Resource source="CF" title="SOS Dynamic Programming" url="blog/entry/45223"> Sum over Subsets DP </Resource>
</Resources>
## Problems
@ -58,4 +60,4 @@ You can often use this to solve subtasks.
(fill in? more probs?)
<Problems problems={metadata.problems.broken} />
<Problems problems={metadata.problems.broken} />

View file

@ -204,7 +204,7 @@ Naively, this would take up $O(N^2)$ memory, but *path compression* enables it t
<Problems problems={metadata.problems.tree} />
### 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)
```
</CPPSection>
<JavaSection />
</LanguageSection>
<PySection />
### 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.
<LanguageSection>
<CPPSection>
```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()
{
}
```
</CPPSection>
</LanguageSection>
### 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!
<LanguageSection>
<CPPSection>
<!-- https://codeforces.com/edu/course/2/lesson/2/2/practice/contest/269103/submission/85759835 - This submission contains both -->
```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;
}
}
}
```
</CPPSection>
</LanguageSection>