Hwsoln 11
Hwsoln 11
Homework 11 Solutions
(a) 2n = O(n). TRUE. We can see this by letting c = 2, and noting that 2n ≤
cn = 2n for all n ≥ 1. Thus, the definition of big-O holds for c = 2 and
n0 = 1.
(b) n2 = O(n). FALSE. For it to be true, we would need that there exist positive
constants c and n0 such that n2 ≤ cn for all n ≥ n0 . By dividing both sides
by n, we see that “n2 ≤ cn for all n ≥ n0 ” is true if and only if “n ≤ c for all
n ≥ n0 ” is true, but clearly there cannot exist constants c and n0 for which the
last statement is true.
(c) n2 = O(n log2 n). FALSE. To see why, note that n2 = O(n log2 n) if and
only if there exist positive constants c and n0 such that n2 ≤ cn log2 n for all
n ≥ n0 , which holds if and only if
n2
≤ c for all n ≥ n0 . (1)
n log2 n
By cancelling out an n from the numerator and denominator, we can rewrite
equation (1) as n/(log2 n) ≤ c for all n ≥ n0 . Writing n = n1/2 n1/2 , we see
that the last statement is true if and only if [n1/2 /(log n)]2 ≤ c for all n ≥ n0 .
But because we know that log n = o(n1/2 ), we have that n1/2 /(log n) → ∞ as
n → ∞, so [n1/2 /(log n)]2 ≤ c cannot be true for all n ≥ n0 for any constant
c.
(d) n log n = O(n2 ). TRUE. Because log n = O(n), there exist positive constants
c and n0 such that log n ≤ cn for all n ≥ n0 . Multiplying both sides by n gives
n log n ≤ cn2 for all n ≥ n0 for the same positive constants c and n0 , so
n log n = O(n2 ).
(e) 3n = O(2n ). FALSE. Suppose that it were true. Then there exists constants c
and n0 such that 3n ≤ c2n for all n ≥ n0 . The last requirement is equivalent to
(3/2)n ≤ c for all n ≥ n0 . However, (3/2)n → ∞ as n → ∞, so (3/2)n ≤ c
cannot be true for all n ≥ n0 for any constant c.
(f) 3n = 2O(n) . TRUE because 3n = 2n log2 3 = 2O(n) .
n n
(g) 22 = O(22 ). TRUE. Any function f (n) is O(f (n)).
1
2. Let b > 1 be a constant. Show that O(t(n)) × O(bt(n) ) = 2O(t(n)) .
Answer: Let f1 (n) = O(t(n)) and f2 (n) = O(bt(n) ), so we want to show that
f1 (n)f2 (n) = 2O(t(n)) . Because f1 (n) = O(t(n)), there exist constants c1 and n1
such that f1 (n) ≤ c1 t(n) for all n ≥ n1 . Because f2 (n) = O(bt(n) ), there exist
constants c2 and n2 such that f2 (n) ≤ c2 bt(n) for all n ≥ n2 . Consequently, letting
c0 = c1 c2 , we get
f1 (n) f2 (n) ≤ c0 t(n) bt(n)
for all n ≥ n0 ≡ max(n1 , n2 ). Now recall that x = 2log2 (x) for any x, so
t(n)
c0 t(n) bt(n) = 2log2 (c0 t(n) b )
= 2log2 (c0 )+log2 (t(n))+t(n) log2 (b)
= 2O(t(n))
because log2 (t(n)) = O(t(n)).
3. (a) Show that P is closed under union.
Answer: Suppose that language L1 ∈ P and language L2 ∈ P. Thus, there are
polynomial-time TMs M1 and M2 that decide L1 and L2 , respectively. Specifi-
cally, suppose that M1 has running time O(nk1 ), and that M2 has running time
O(nk2 ), where n is the length of the input w, and k1 and k2 are constants. A
Turing machine M3 that decides L1 ∪ L2 is the following:
M3 = “On input w:
1. Run M1 with input w. If M1 accepts, accept.
2. Run M2 with input w. If M2 accepts, accept.
Otherwise, reject.”
Thus, M3 accepts w if and only if either M1 or M2 (or both) accepts w. The
running time of M3 is O(nk1 ) + O(nk2 ) = O(nmax(k1 ,k2 ) ), which is still polyno-
mial in n; i.e., the sum of two polynomials is also polynomial. Thus, the overall
running time of M3 is also polynomial.
(b) Show that P is closed under concatenation.
Answer: Suppose that language L1 ∈ P and language L2 ∈ P. Thus, there are
polynomial-time TMs M1 and M2 that decide L1 and L2 , respectively. Specifi-
cally, suppose that M1 has running time O(nk1 ), and that M2 has running time
O(nk2 ), where n is the length of the input, and k1 and k2 are constants. A
Turing machine M3 that decides the concatenation L1 ◦ L2 is the following:
M3 = “On input w = a1 a2 · · · an , with each ai ∈ Σ a symbol:
1. For i = 0, 1, 2, . . . , n, do
2. Run M1 with input w1 = a1 a2 · · · ai , and
run M2 with input w2 = ai+1 ai+1 · · · an .
If both M1 and M2 accept, accept.
3. If none of the iterations in Stage 2 accept, reject.”
2
The TM M3 checks every possible way of splitting the input w into two parts w1
and w2 , and checks if the first part w1 is accepted by M1 (i.e., w1 ∈ L1 ) and
the second part w2 is accepted by M2 (i.e., w2 ∈ L2 ), so that w1 w2 ∈ L1 ◦ L2 .
Suppose that the input w to M3 has length |w| = n. Stage 2 is executed at most
n + 1 times. Each time Stage 2 is executed, M1 and M2 are run on strings w1
and w2 with |w1 | ≤ |w| = n and |w2 | ≤ |w| = n. Thus, running M1 on w1
takes O(nk1 ) time, and running M2 on w2 takes O(nk2 ) time, so Stage 2 runs
in time O(nk1 ) + O(nk2 ) = O(nmax(k1 ,k2 ) ), which is polynomial in n. Because
Stage 2 is executed at most n + 1 times, we get that the time complexity of M3 is
O(n + 1)O(nmax(k1 ,k2 ) ) = O(n1+max(k1 ,k2 ) ), which is polynomial in n. Hence,
the overall running time of M3 is polynomial in n.
(c) Show that P is closed under complementation.
Answer: Suppose that language L1 ∈ P, so there is a polynomial-time TM M1
that decides L1 . A Turing machine M2 that decides L1 is the following:
M2 = “On input w:
1. Run M1 with input w.
If M1 accepts, reject; otherwise, accept.”
Answer: Let G = (V, E) be a graph with a set V of vertices and a set E of edges.
We enumerate all triples (u, v, w) with vertices u, v, w ∈ V and u < v < w, and then
check whether or not all three edges (u, v), (v, w) and (u, w) exist in E. Enumeration
of all triples requires O(|V |3 ) time. Checking whether or not all three edges belong
to E takes O(|E|) time. Thus, the overall time is O(|V |3 |E|), which is polynomial
in the length of the input hGi. Therefore, TRIANGLE ∈ P.
Remark: Note that for TRIANGLE , we are looking for a clique of fixed size 3, so
even though the 3 is in the exponent of the time bound, the exponent is a constant, so
the time bound is polynomial. We could modify the above algorithm for TRIANGLE
to work for CLIQUE = { hG, ki | G is an undirected graph with a k-clique } by enu-
merating all collections of k vertices, where k is the size of the clique desired. But the
number of such collections is
|V | |V |!
= = O(|V |k ),
k k!(|V | − k)!
3
another algorithm for CLIQUE that does run in polynomial time. However at this
time, it is currently unknown if CLIQUE ∈ P or CLIQUE 6∈ P. Because CLIQUE is
NP-complete, this question will be answered if anyone solves the P vs. NP problem,
which is still unresolved.
5. Using the polynomial-time algorithm for context-free language recognition (i.e., the
CYK algorithm or dynamic programming), fill out the table for string w = abba and
CFG G:
S → RT
R → TR | a
T → TR | b
1 2 3 4
1
2
3
4
string a b b a
Note that we numbered the rows and columns, and we wrote the string abba along
the bottom of the table. We will fill in the table a diagonal at a time, starting with
the main diagonal. Once one diagonal is filled in, we move to the diagonal directly
above it. The entry table(i, j) corresponds to the substring starting in position i and
ending in position j, and we put into table(i, j) those variables that we can start with
to generate that substring.
We start by filling in the main diagonal, which consists of the entries table(1, 1),
table(2, 2), table(3, 3), and table(4, 4). Entry table(1, 1) corresponds to the sub-
string starting in position 1 and ending in position 1, which is the substring a. Because
the given CFG is in Chomsky normal form, the only way a variable can generate this
substring is if there is a rule that has this variable go directly to a. Because there
is a rule R → a, we add the variable R into table(1, 1). There are no other rules
with a on the right side, so we don’t add any other variables to table(1, 1); hence,
table(1, 1) = {T }.
1 2 3 4
1 R
2
3
4
string a b b a
4
We now move to the main diagonal’s next entry, table(2, 2). This corresponds to the
substring starting in position 2 and ending in position 2, which is the substring b. The
only way to generate this substring is through the rule T → b, so table(2, 2) = {T }.
1 2 3 4
1 R
2 T
3
4
string a b b a
Similarly, for entries table(3, 3) and table(4, 4), which correspond to substrings b and
a, respectively, we have table(3, 3) = {T } and table(4, 4) = {R}.
1 2 3 4
1 R
2 T
3 T
4 R
string a b b a
Now that the main diagonal is complete, we next fill in the diagonal just above it.
Entry table(1, 2) corresponds to the substring starting in position 1 and ending in
position 2, which is the substring ab. We can divide this substring into two shorter
parts, a and b, and we see how we can generate these two shorter parts.
For the first part a, which starts in position 1 and ends in position 1, we look in
entry table(1, 1) to see that R can generate this part a.
For the second part b, which starts in position 2 and ends in position 2, we look
in entry table(2, 2) to see that T can generate this part b.
Now if we have a rule in which the right side pairs a variable from table(1, 1) with a
variable from table(2, 2), then the variable on the left side of the rule can generate the
current substring ab. Specifically, we are looking for rules whose right sides are from
table(1, 1) ◦ table(2, 2). Since table(1, 1) = {R} and table(2, 2) = {T }, we have
that table(1, 1) ◦ table(2, 2) = {RT }, so we look for rules with RT on the right side.
For example, there is a rule S → RT , so the variable S can generate the current
substring ab. To see why, consider the right side RT of the rule S → RT .
Entry table(1, 1) tells us that the R on the right side can generate a, and entry
∗
table(2, 2) tells us that the T on the right side can generate b. Thus, S ⇒ RT ⇒
ab, so S can generate ab.
We have now determined that S can generate the current substring ab, which starts in
position 1 and ends in position 2, so we add S into table(1, 2); hence, table(1, 2) =
{S}.
5
1 2 3 4
1 R S
2 T
3 T
4 R
string a b b a
Now we consider the next entry in the current diagonal. This is table(2, 3), which
corresponds to the substring starting in position 2 and ending in position 3, which
is the substring bb. We divide this substring into two smaller parts, b and b, and we
determine how we can generate these two parts.
For the first part b, which starts in position 2 and ends in position 2, the entry
table(2, 2) tells us that T can generate this part b.
For the second part b, which starts in position 3 and ends in position 3, the entry
table(3, 3) tells us that T can generate this part b.
Now if we have a rule in which the right side is from table(2, 2) ◦ table(3, 3) (i.e.,
the right side pairs a variable from table(2, 2) with a variable from table(3, 3)), then
the variable on the left side of the rule can generate the current substring bb. Since
table(2, 2) = {T } and table(3, 3) = {T }, we have table(2, 2) ◦ table(3, 3) =
{T T }, so we are looking for rules that have T T on the right side. But there are no
rules with T T on the right side, so it is impossible to generate the current substring
bb using the rules of the CFG; thus, we put a dash “—” in entry (2, 3) to denote that
table(2, 3) = ∅.
1 2 3 4
1 R S
2 T —
3 T
4 R
string a b b a
Using similar reasoning for entry table(3, 4), we look for rules that have right sides
from table(3, 3) ◦ table(4, 4) = {T } ◦ {R} = {T R}. Thus, we look for rules with
T R on the right side, which leads us to put R and T in table(3, 4), so table(3, 4) =
{R, T }.
1 2 3 4
1 R S
2 T —
3 T R, T
4 R
string a b b a
6
Now that the second diagonal is complete, we next fill in the diagonal just above
it. Entry table(1, 3) corresponds to the substring starting in position 1 and ending in
position 3, which is the substring abb. We can divide this substring into two nonempty
parts in two different ways: a concatenated with bb, and ab concatenated with b.
First consider splitting abb into parts a and bb.
For the first part a, which starts in position 1 and ends in position 1, entry
table(1, 1) = {R} tells us that R can generate this part a.
For the second part bb, which starts in position 2 and ends in position 3, entry
table(2, 3) = ∅ tells us that nothing can generate this part bb.
For the first part ab, which starts in position 1 and ends in position 2, entry
table(1, 2) = {S} tells us that S can generate this part ab.
For the second part b, which starts in position 3 and ends in position 3, entry
table(3, 3) = {T } tells us that T can generate this part b.
Thus, if we have a rule with right side from table(1, 2) ◦ table(3, 3) = {S} ◦ {T } =
{ST }, then the variable on the left side of the rule can generate the current substring
abb. We are thus looking for rules with right side ST , and we add the variables on the
left sides of these rules to table(1, 3). In this case, there are no rules with ST on the
right side, so it is impossible to generate the current substring abb using the split that
concatenates ab with b. (Actually, we don’t have to even look at the rules to determine
that no rule has ST on the right side since the start variable S cannot appear on the
right side of any rule because the CFG is in Chomsky normal form.) Since the other
way of splitting abb as a concatenated with bb also was impossible, we then see it is
not possible to generate abb using the CFG, so table(1, 3) = ∅, which we denote with
a dash.
1 2 3 4
1 R S —
2 T —
3 T R, T
4 R
string a b b a
Let us now review how we filled in entry table(1, 3). We looked for rules that had on
the right side either
a variable from table(1, 1) paired with a variable from table(2, 3), i.e., a right
side from table(1, 1) ◦ table(2, 3), or
7
a variable from table(1, 2) paired with a variable from table(3, 3), i.e., a right
side from table(1, 2) ◦ table(3, 3).
Thus, to fill in entry table(1, 3), we pair entries by going across row 1 and down column
3. In general, to fill in entry table(i, j), we pair entries by going across row i and down
column j, i.e., we look for rules with right sides from table(i, i) ◦ table(i + 1, j), or
table(i, i + 1) ◦ table(i + 2, j), or . . . , or table(i, j − 1) ◦ table(n, j).
Next we fill in entry table(2, 4), which corresponds to the substring starting in position
2 and ending in position 4, which is the substring bba. Using the observation from the
previous paragraph, we thus want to pair entries going across row 2 and down column
4. In particular, we look for rules with right sides from
table(2, 2) ◦ table(3, 4), i.e., we pair a variable from table(2, 2) with a variable
from table(3, 4), or
table(2, 3) ◦ table(4, 4), i.e., we pair a variable from table(2, 3) with a variable
from table(4, 4).
1 2 3 4
1 R S —
2 T — R, T
3 T R, T
4 R
string a b b a
This completes the third diagonal, so now we move to the next diagonal. The entry
table(1, 4) corresponds to the substring starting in position 1 and ending in position
4, which is the substring abba. To determine how we can generate this substring, we
pair entries in the table by going across row 1 and down column 4. In particular, we
pair
8
table(1, 1) ◦ table(2, 4) = {R} ◦ {R, T } = {RR, RT }, or
table(1, 2) ◦ table(3, 4) = {S} ◦ {R, T } = {SR, ST }, or
table(1, 3) ◦ table(4, 4) = ∅ ◦ {R} = ∅.
For any rule that has any of these right sides, we add the variable on the left of the
rule to entry table(1, 4). The only rule with these possible right sides are S → RT ,
so we add S to entry table(1, 4).
1 2 3 4
1 R S — S
2 T — R, T
3 T R, T
4 R
string a b b a
The table is now complete since we have filled in the upper triangle. To determine if
the CFG can generate original string abba, which is the substring starting in position
1 and ending in position 4, we check if the starting variable S ∈ table(1, 4). Since it
is, CFG G generates the string abba. If S were not in the upper right corner, then the
CFG would not generate the string.