// Arup Guha
// 4/3/2014
// Solution to 2015 NAIPC Problem G: Stretching

// Note: This is probably messier than it needs to be. My core idea was correct, but I
//       initially had an implementation error. I tried many things to fix it that
//       complicated the code and once I identified the key issue, it's likely that
//       several of the items I added were unnecessary. Maybe if I have time later, I'll
//       clean it up.

import java.util.*;

public class stretching {

	public static char[] str;
	public static Boolean[][][] memo;
	public static int[] freq;
	public static int atomicLen;
	public static int strGCD;

	public static void main(String[] args) {

		// Get input.
		Scanner stdin = new Scanner(System.in);
		str = stdin.next().toCharArray();

		// Get total letter frequencies.
		freq = new int[26];
		for (int i=0; i<str.length; i++)
			freq[str[i]-'a']++;
		strGCD = gcd(freq);

		// Store atomic string data.
		for (int i=0; i<26; i++)
			freq[i] /= strGCD;
		atomicLen = str.length/strGCD;

		// Simple case...
		if (strGCD == 1)
			System.out.println(new String(str));

		// Here we must do stuff.
		else
			System.out.println(solve());
	}

	// Some elements of array are positive.
	public static int gcd(int[] array) {

		int i = 0;

		// Go to first non-zero element and set as gcd.
		while (array[i] == 0) i++;
		int res = array[i];
		i++;

		// Now do gcd with anything useful.
		while (i < 26) {
			if (array[i] > 0)
				res = gcd(res, array[i]);
			i++;
		}

		return res;
	}

	public static int gcd(int a, int b) {
		if (a == 0) return b;
		if (b == 0) return a;
		return gcd(b, a%b);
	}

	// Assumes a and b are of same length.
	public static boolean equal(int[] a, int[] b) {
		for (int i=0; i<a.length; i++)
			if (a[i] != b[i])
				return false;
		return true;
	}

	// Returns str[start..start+len-1] in string form.
	public static String mkStr(int start, int len) {
		char[] res = new char[len];
		for (int i=start; i<start+len; i++)
			res[i-start] = str[i];
		return new String(res);
	}

	public static String solve() {

		// Iterate through valid string lengths, except last.
		for (int rep=1; rep<strGCD; rep++) {
			if (strGCD%rep == 0) {

				TreeSet<String> possible = new TreeSet<String>();

				// Set up letter frequencies for all strings of this length.
				int[] thisFreq = new int[26];
				for (int i=0; i<26; i++)
					thisFreq[i] = rep*freq[i];
				int thisLen = rep*atomicLen;

				// Get letter frequency of left end.
				int[] strFreq = new int[26];
				for (int i=0; i<thisLen; i++)
					strFreq[str[i]-'a']++;

				for (int i=0; i<=str.length-thisLen; i++) {
					if (equal(strFreq, thisFreq))
						possible.add(mkStr(i, thisLen));

					// Just subtract first letter, add new last letter.
					strFreq[str[i]-'a']--;
					if (i+thisLen < str.length) strFreq[str[i+thisLen]-'a']++;
				}

				// Go through TreeSet in order.
				while (possible.size() > 0) {

					// Get the next candidate.
					char[] tryStr = possible.pollFirst().toCharArray();

					// Set up memo table.
					memo = new Boolean[tryStr.length][str.length+1][str.length+1];
					for (int i=0; i<tryStr.length; i++) {
						for (int j=0; j<str.length; j++) {
							if (tryStr[i] != str[j])
								Arrays.fill(memo[i][j], false);
							else
								Arrays.fill(memo[i][j], null);
						}
					}

					// Put in all straight matches.
					for (int i=0; i<=str.length-tryStr.length; i++) {
						boolean match = true;
						for (int j=0; j<tryStr.length; j++) {
							if (str[i+j] != tryStr[j]) {
								match = false;
								break;
							}
						}
						if (match) {
							for (int k=0; k<tryStr.length; k++)
								memo[k][i+k][i+tryStr.length] = true;
						}
					}

					// If it works, return it!
					if (solveString(0, 0, str.length, tryStr)) return new String(tryStr);
				}
			}
		}

		// If we get here, nothing worked :(
		return new String(str);
	}

	public static boolean solveString(int Pindex, int Lindex, int Rindex, char[] s) {

		// Got to the end of a match...try to match the rest.
		if (Pindex == s.length) {
			if (Lindex == Rindex)
				return true;
			if (Lindex < Rindex)
				return solveString(0, Lindex, Rindex, s);
		}

		// Other base cases.
		if (Pindex >= s.length || Lindex > str.length || Rindex > str.length) return false;
		if (memo[Pindex][Lindex][Rindex] != null) return memo[Pindex][Lindex][Rindex];

		// Rule this case out! (Might be redundant...might have done this in the memo table)
		if (s[Pindex] != str[Lindex]) {
			memo[Pindex][Lindex][Rindex] = false;
			return false;
		}

		// Try splitting into two separate solutions! (Might be unnecessary, due to my base case...)
		for (int i=Lindex-Pindex+s.length; i<Rindex; i+=s.length) {
			if (solveString(Pindex+1, Lindex+1, i, s) && solveString(0, i, Rindex, s)) {
				memo[0][Lindex][Rindex] = true;
				return true;
			}
		}

		// Just match this letter and then try to match next.
		boolean res = solveString(Pindex+1, Lindex+1, Rindex, s);
		if (res) {
			memo[Pindex][Lindex][Rindex] = true;
			return true;
		}

		// Try having a full solution inserted between character Pindex and Pindex+1.
		for (int len=s.length;;len+=s.length) {

			if ( (Rindex - (Lindex+1+len)) < s.length-Pindex-1) break;
			boolean next = solveString(0, Lindex+1, Lindex+1+len, s);

			// Can't build off this solution so go to next.
			if (!next) continue;

			// Not enough room for the rest of the characters we HAVE to cram in there.
			res = solveString(Pindex+1, Lindex+1+len, Rindex, s);
			if (res) {
				memo[Pindex][Lindex][Rindex] = true;
				return true;
			}
		}

		// Never made it :(
		memo[Pindex][Lindex][Rindex] = false;
		return false;
	}
}