Problem:
Problem E: Alice in Foxland

- The world is made of foxes; people with watchful eyes will find foxes in every
fragment of the world.

Defoxyrenardnucleic Acids (or DNAs for short) and Renardnucleic Acids (or RNAs) are similar
organic molecules contained in organisms. Each of those molecules consists of a sequence of 26
kinds of nucleobases. We can represent such sequences as strings by having each lowercase letter
from ‘a’ to ‘z’ denote one kind of nucleobase. The only difference between DNAs and RNAs is
the way of those nucleobases being bonded.

In the year of 2323, Prof. Fuchs discovered that DNAs including particular substrings act as
catalysts, that is, accelerate some chemical reactions. He further discovered that the reactions
are accelerated as the DNAs have longer sequences. For example, DNAs including the sequence
“fox” act as catalysts that accelerate dissolution of nitrogen oxides (NOx ). The DNAs “redfox”
and “cutefoxes” are two of the instances, and the latter provides more acceleration than the
former. On the other hand, the DNA “foooox” will not be such a catalyst, since it does not
include “fox” as a substring.

DNAs can be easily obtained by extraction from some plants such as glory lilies. However,
almost all of extracted molecules have different sequences each other, and we can obtain very
few molecules that act as catalysts. From this background, many scientists have worked for
finding a way to obtain the demanded molecules.

In the year of 2369, Prof. Hu finally discovered the following process:

Prepare two DNAs X and Y .

Generate RNAs X' and Y' with their sequences copied from the DNAs X and Y respectively.

Delete zero or more bases from X' using some chemicals to obtain an RNA X''.

Also delete zero or more bases from Y' to obtain an RNA Y'' , which has the same sequence
as X'' .

Obtain a resulting DNA Z from the two RNAs X'' and Y''
same sequence as X'' and Y''.

Figure 1: New Method for Generation of DNAs

The point is use of RNAs. It is difficult to delete specific bases on DNAs but relatively easy on
RNAs. On the other hand, since RNAs are less stable than DNAs, there is no known way to
obtain RNAs directly from some organisms. This is why we obtain RNAs from DNAs.

Alice is a researcher in Tail Environmental Natural Catalyst Organization. She is now requested
to generate DNAs with particular substrings, applying Hu’s method to some pairs of DNAs.
Since longer DNAs are preferred, she wants a means of knowing the longest possible DNAs. So
she asked you for help.

Your task is to write a program that outputs the sequence of the longest possible DNA which
can be generated from the given pair of DNAs X and Y and contains the given substring C.

Input

The input consists of multiple datasets. Each dataset consists of three lines. The first and
second lines contain the sequences X and Y respectively. The third line contains the substring
C. Each of the sequences and the substrings contains only lowercase letters (‘a’–‘z’) and has
the length between 1 and 1600 inclusive.

The input is terminated by a line with “*”.

Output

For each dataset, output the longest sequence in a line. If DNAs with the substring C cannot
be obtained in any way, output “Impossible” instead. Any of them is acceptable in case there
are two or more longest DNAs possible.

Sample Input

czujthebdgfoliskax
bdgchuptzefliskaox
fox
fennec
oinarisama
xiaorong
customizedrevisedfoooox
accurateredundantfooooooooox
fox
*

Output for the Sample Input

cutefox
Impossible
cuteredfox

Solution in JAVA (judge verdict: Memory Limit Exceeded)

import java.awt.Point;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Scanner;

public class Main {

	Scanner sc;

	Main() {
		sc = new Scanner(System.in);
	}

	String rev(String s) {
		char[] r = s.toCharArray();
		char[] r2 = new char[r.length];
		for (int i = 0; i < r.length; i++) {
			r2[i] = r[s.length() - 1 - i];
		}
		return new String(r2);
	}

	void run() {
		int s1[][] = new int[1611][1611];
		int dp1[][] = new int[1611][1611];
		int s2[][] = new int[1611][1611];
		int dp2[][] = new int[1611][1611];

		for (;;) {
			String x1 = rev(sc.next());
			if (x1.equals("*"))
				break;
			String y1 = rev(sc.next());
			String zz = sc.next();
			String z1 = rev(zz);
			{
				String y = y1;
				String x = x1;
				String z = z1;

				boolean ok = true;
				for (int i = 0, cnt = 0; i < x.length(); i++) {
					if (x.charAt(x.length() - 1 - i) == z.charAt(z.length() - 1
							- cnt)) {
						cnt++;
						if (cnt == z.length()) {
							break;
						}
					}
					if (i == x.length() - 1)
						ok = false;
				}
				for (int i = 0, cnt = 0; i < y.length(); i++) {
					if (y.charAt(y.length() - 1 - i) == z.charAt(z.length() - 1
							- cnt)) {
						cnt++;
						if (cnt == z.length()) {
							break;
						}
					}
					if (i == y.length() - 1)
						ok = false;
				}
				if (!ok) {
					System.out.println("Impossible");
					continue;
				}
			}

			// System.out.println(x);
			// System.out.println(y);

			{
				String y = y1;
				String x = x1;
				String z = z1;

				s1 = new int[x.length() + 1][y.length() + 1];
				dp1 = new int[x.length() + 1][y.length() + 1];
				for (int i = 0; i < x.length(); i++) {
					for (int j = 0; j < y.length(); j++) {
						if (x.charAt(i) == y.charAt(j)) {
							dp1[i + 1][j + 1] = dp1[i][j] + 1;
							s1[i + 1][j + 1] = 1;
						} else {
							if (dp1[i][j + 1] < dp1[i + 1][j]) {
								dp1[i + 1][j + 1] = dp1[i + 1][j];
								s1[i + 1][j + 1] = 0;
							} else {
								dp1[i + 1][j + 1] = dp1[i][j + 1];
								s1[i + 1][j + 1] = -1;
							}
						}
					}
				}
			}

			{
				String y = rev(y1);
				String x = rev(x1);
				String z = rev(z1);

				for (int i = 0; i < x.length(); i++) {
					for (int j = 0; j < y.length(); j++) {
						if (x.charAt(i) == y.charAt(j)) {
							dp2[i + 1][j + 1] = dp2[i][j] + 1;
							s2[i + 1][j + 1] = 1;
						} else {
							if (dp2[i][j + 1] < dp2[i + 1][j]) {
								dp2[i + 1][j + 1] = dp2[i + 1][j];
								s2[i + 1][j + 1] = 0;
							} else {
								dp2[i + 1][j + 1] = dp2[i][j + 1];
								s2[i + 1][j + 1] = -1;
							}
						}
					}
				}
			}

			HashMap<Integer, Integer> lxm = new HashMap<Integer, Integer>();
			for (int i = 0; i < x1.length(); i++) {
				int s = i;
				int e = -1;
				if (x1.charAt(i) == z1.charAt(0)) {
					boolean ok = false;
					int j = i;
					for (int cnt = 0; j < x1.length() && cnt < z1.length(); j++) {
						if (x1.charAt(j) == z1.charAt(cnt)) {
							cnt++;
							if (cnt == z1.length()) {
								ok = true;
								break;
							}
						}
					}
					if (ok) {
						e = j;
						lxm.put(e, s);
						i = s + 1;
					} else {
						break;
					}
				}
			}

			HashMap<Integer, Integer> lym = new HashMap<Integer, Integer>();
			for (int i = 0; i < y1.length(); i++) {
				int s = i;
				int e = -1;
				if (y1.charAt(i) == z1.charAt(0)) {
					boolean ok = false;
					int j = i;
					for (int cnt = 0; j < y1.length() && cnt < z1.length(); j++) {
						if (y1.charAt(j) == z1.charAt(cnt)) {
							cnt++;
							if (cnt == z1.length()) {
								ok = true;
								break;
							}
						}
					}
					if (ok) {
						e = j;
						lym.put(e, s);
						i = s + 1;
					} else {
						break;
					}
				}
			}

			int max = -1;
			Point mx = new Point(-1, -1), my = new Point(-1, -1);

			for (int i : lxm.keySet()) {
				for (int j : lym.keySet()) {
					Point x = new Point(lxm.get(i),i); 
					Point y = new Point(lym.get(j),j);
					int value = dp1[x.x][y.x]
							+ dp2[x1.length() - 1 - x.y][y1.length() - 1 - y.y];
					if (max < value) {
						mx = x;
						my = y;
						max = value;
					}
				}
			}
			if (mx.x == -1) {
				System.out.println("Impossible");
				continue;
			}

			String ans = "";
			for (int a = mx.y, b = my.y; a < x1.length() - 1
					&& b < y1.length() - 1;) {
				if (s2[a][b] == 1) {
					ans += (x1.charAt(a + 1));
					a++;
					b++;
				} else if (s2[a][b] == 0) {
					b++;
				} else {
					a++;
				}
			}
			System.out.print(rev(ans));

			System.out.print(zz);

			for (int a = mx.x, b = my.x; a > 0 && b > 0;) {
				if (s1[a][b] == 1) {
					System.out.print(x1.charAt(a - 1));
					a--;
					b--;
				} else if (s1[a][b] == 0) {
					b--;
				} else {
					a--;
				}
			}
			System.out.println();

			// System.out.println(dp[x.length()][y.length()]+z.length());
		}

	}

	public static void main(String[] args) {
		Main m = new Main();
		m.run();
	}

}