package main
import (
"bufio"
"fmt"
"math"
"os"
)
type Key struct {
a uint64
b uint64
}
const (
base1 uint64 = 911382323
base2 uint64 = 972663749
)
var h1, h2, p1, p2 []uint64
func sub(h, p []uint64, l, r int) uint64 {
return h[r] - h[l-1]*p[r-l+1]
}
func eq(l1, r1, l2, r2 int) bool {
return sub(h1, p1, l1, r1) == sub(h1, p1, l2, r2) &&
sub(h2, p2, l1, r1) == sub(h2, p2, l2, r2)
}
func main() {
in := bufio.NewReaderSize(os.Stdin, 1<<20)
out := bufio.NewWriterSize(os.Stdout, 1<<20)
defer out.Flush()
var s string
fmt.Fscan(in, &s)
n := len(s)
if n == 0 {
return
}
B := int(math.Sqrt(float64(n))) + 1
h1 = make([]uint64, n+1)
h2 = make([]uint64, n+1)
p1 = make([]uint64, n+1)
p2 = make([]uint64, n+1)
p1[0], p2[0] = 1, 1
for i := 1; i <= n; i++ {
p1[i] = p1[i-1] * base1
p2[i] = p2[i-1] * base2
}
chars := make([]byte, n+1)
occKey := make([]Key, n+1)
occ := make(map[Key][]int, n)
top := 0
for i := 0; i < n; i++ {
c := s[i]
top++
chars[top] = c
v := uint64(c-'a'+1)
h1[top] = h1[top-1]*base1 + v
h2[top] = h2[top-1]*base2 + v
var curKey Key
if top >= B {
curKey = Key{
sub(h1, p1, top-B+1, top),
sub(h2, p2, top-B+1, top),
}
occKey[top] = curKey
occ[curKey] = append(occ[curKey], top)
}
found := 0
lim := top / 2
small := B
if lim < small {
small = lim
}
for k := 1; k <= small; k++ {
if eq(top-2*k+1, top-k, top-k+1, top) {
found = k
break
}
}
if found == 0 && top >= B && lim > B {
lst := occ[curKey]
for idx := len(lst) - 2; idx >= 0; idx-- {
j := lst[idx]
if j*2 < top {
break
}
k := top - j
if k <= B {
continue
}
if eq(top-2*k+1, top-k, top-k+1, top) {
found = k
break
}
}
}
if found > 0 {
newTop := top - found
for t := top; t > newTop; t-- {
if t >= B {
k := occKey[t]
lst := occ[k]
if len(lst) == 1 {
delete(occ, k)
} else {
occ[k] = lst[:len(lst)-1]
}
}
}
top = newTop
}
}
out.Write(chars[1 : top+1])
}