Wenn zwei Zeichenfolgen , schreiben wir für ihre Verkettung. Bei einer Zeichenkette und Integer , wir schreiben für die Verkettung von Kopien von . Wenn wir nun einen String haben, können wir ihn mit dieser Notation 'komprimieren', dh kann geschrieben werden als . Nennen wir das Gewicht einer Komprimierung die Anzahl der Zeichen, die darin vorkommen, sodass das Gewicht von zwei und das Gewicht von (eine Komprimierung von ) ist. ist drei (separate werden separat gezählt).
Betrachten Sie nun das Problem, die 'leichteste' Komprimierung eines gegebenen Strings mit berechnen S | = n . Nach einigem Nachdenken gibt es einen offensichtlichen dynamischen Programmieransatz, der in oder O ( n 3 ) abläuft. je nach genauem Ansatz .
Mir wurde jedoch mitgeteilt, dass dieses Problem in gelöst werden kann , obwohl ich keine Quellen dazu finde. Insbesondere wurde dieses Problem in einem kürzlich durchgeführten Programmierwettbewerb (Problem K hier , letzte zwei Seiten) angegeben. Während der Analyse wurde ein -Algorithmus vorgestellt, und am Ende wurde die pseudoquadratische Grenze erwähnt ( hier bei der Vier-Minuten-Marke). Leider bezog sich der Moderator nur auf 'ein kompliziertes Wortkombinatorisches Lemma', und jetzt bin ich hierher gekommen, um nach der Lösung zu fragen :-)
quelle
Antworten:
If I'm not misunderstanding you, I think the minimum cost factorization can be calculated inO(n2) time as follows.
For each index i, we will calculate a bunch of values(pℓi,rℓi) for ℓ=1,2,… as follows. Let p1i≥1 be the smallest integer such that there is an integer r≥2 satisfying S[i−rp1i+1,i−p1i]=S[i−(r−1)p1i+1,i]. For this particular p1i , let r1i be the largest r with this property.
If no such pi exists, set Li=0 so we know there are zero (pℓi,rℓi) values for this index.
Letp2i be the smallest integer strictly bigger than (r1i−1)p1i satisfying, likewise,
S[i−r2ip2i+1,i−p2i]=S[i−(r2i−1)p2i+1,i] r2i≥2 r2i p2i pℓi (rℓ−1i−1)pℓ−1i pℓi exists, then Li=ℓ−1 .
Note that for each index i, we haveLi=O(log(i+1)) due to pℓi values increasing geometrically with ℓ . (if pℓ+1i exists, it's not just strictly bigger than (rℓi−1)pℓi but bigger than that by at least pℓi/2 . This establishes the geometric increase.)
We already observed above that∑jLj=O(∑jlog(j+1))=Θ(nlogn) by bounding the sum term by term. But actually if we look at the whole sum, we can prove something sharper.
Consider the suffix treeT(S←) of the reverse of S (i.e., the prefix tree of S). We will charge each contribution to the sum ∑iLi to an edge of T(S←) so that each edge will be charged at most once. Charge each pji to the edge emanating from nca(v(i),v(i−pji)) and going towards v(i−pji) . Here v(i) is the leaf of the prefix tree corresponding to S[1..i] and nca denotes the nearest common ancestor.
This shows thatO(∑iLi)=O(n) . The values (pji,rji) can be calculated in time O(n+∑iLi) by a traversal of the suffix tree but I will leave the details to a later edit if anyone is interested.
Let me know if this makes sense.
quelle
There is your initial string S of length n. Here is the pseudo-code of the method.
I intentionally gave little details on "end brackets" as it needs lot of steps to stack and unstack which would let the core method unclear. The idea is to test an eventual further contraction inside the first one. for exemple ABCBCABCBC => (ABCBC)² => (A(BC)²)².
So the main point is to look for large periods first. Note that S[i] is the ith term of S skipping any "(", ")" or power.
This is globally O(n²log(n)).
quelle