Problem:
Score : 200 points

Problem Statement

For a string S consisting of the uppercase English letters P and D, let the doctoral and postdoctoral quotient of S be the total number of occurrences of D and PD in S as contiguous substrings. For example, if S = PPDDP, it contains two occurrences of D and one occurrence of PD as contiguous substrings, so the doctoral and postdoctoral quotient of S is 3.

We have a string T consisting of P, D, and ?.

Among the strings that can be obtained by replacing each ? in T with P or D, find one with the maximum possible doctoral and postdoctoral quotient.

Constraints

1 \leq |T| \leq 2 \times 10^5

T consists of P, D, and ?.

Input

Input is given from Standard Input in the following format:

T

Output

Print one string with the maximum possible doctoral and postdoctoral quotient among the strings that can be obtained by replacing each ? in T with P or D.
If there are multiple such strings, you may print any of them.

Sample Input 1

PD?D??P

Sample Output 1

PDPDPDP

This string contains three occurrences of D and three occurrences of PD as contiguous substrings, so its doctoral and postdoctoral quotient is 6, which is the maximum doctoral and postdoctoral quotient of a string obtained by replacing each ? in T with P or D.

Sample Input 2

P?P?

Sample Output 2

PDPD

Solution in C# (.NET Core 3.1.201) (judge verdict: Wrong Answer)

#nullable enable
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Numerics;
using System.Threading.Tasks;
using static System.Console;
using static System.Math;
using static Func;
using System.Threading;

class Z { static void Main() => new K(); }
class K
{
	int F => int.Parse(Str);
	long FL => long.Parse(Str);
	int[] G => Strs.Select(int.Parse).ToArray();
	uint[] GU => Strs.Select(uint.Parse).ToArray();
	decimal[] GD => Strs.Select(decimal.Parse).ToArray();
	long[] GL => Strs.Select(long.Parse).ToArray();
	string Str => ReadLine();
	string[] Strs => Str.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
	static ulong One(int k) => 1ul << k;
	static ulong All(int k) => One(k) - 1;
	static bool Has(ulong s, int k) => (s & One(k)) != 0;
	const int MOD = 1000000007;
	public K()
	{
		SetOut(new StreamWriter(OpenStandardOutput()) { AutoFlush = false });
		var t = new Thread(Solve, 0);
		t.Start();
		t.Join();
		Out.Flush();
	}
	void Solve()
	{
		var S = Str;
		var N = S.Length;
		// dp[i, c] = max for S[:i+1] if S[i] can be c (otherwise, -INF)
		var dp = new int[N, 2];
		var prev = new int[N, 2];
		var PD = "PD";
		if (S[0] == 'D') { dp[0, 0] = -Inf; dp[0, 1] = 0; }
		else if (S[0] == '?') { dp[0, 0] = 1; dp[0, 1] = 0; }
		else { dp[0, 0] = 0; dp[0, 1] = -Inf; }
		for (var i = 1; i < N; i++)
			for (var j = 0; j < 2; j++)
			{
				if (S[i] != '?' && S[i] != PD[j])
				{
					dp[i, j] = -Inf;
					continue;
				}
				Span<int> x = stackalloc int[2];
				for (var k = 0; k < 2; ++k) x[k] = dp[i - 1, k];
				if (j == 1) { x[0] += 2; x[1] += 1; }
				prev[i, j] = x[0] < x[1] ? 1 : 0;
				dp[i, j] = x[prev[i, j]];
			}
		var T = new char[N];
		var ind = dp[N - 1, 0] < dp[N - 1, 1] ? 1 : 0;
		for (var i = N - 1; i >= 0; i--)
		{
			T[i] = PD[ind];
			ind = prev[i, ind];
		}
		// WriteLine(Max(dp[N - 1, 0], dp[N - 1, 1]));
		WriteLine(new string(T));
	}
}
class X { }
static class Func
{
	public const int Inf = 1073741789;
	public const long InfL = 4011686018427387913L;
	public static T[] ConstantArray<T>(int n, T val) { var a = new T[n]; for (var i = 0; i < n; i++) a[i] = val; return a; }
	public static T[,] ConstantArray<T>(int n, int m, T val) { var a = new T[n, m]; for (var i = 0; i < n; i++) for (var j = 0; j < m; j++) a[i, j] = val; return a; }
	public static T[,,] ConstantArray<T>(int n, int m, int l, T val) { var a = new T[n, m, l]; for (var i = 0; i < n; i++) for (var j = 0; j < m; j++) for (var k = 0; k < l; k++) a[i, j, k] = val; return a; }
	public static T[] MakeArray<T>(int n, Func<int, T> f) { var a = new T[n]; for (var i = 0; i < n; i++) a[i] = f(i); return a; }
	public static T[,] MakeArray<T>(int n, int m, Func<int, int, T> f) { var a = new T[n, m]; for (var i = 0; i < n; i++) for (var j = 0; j < m; j++) a[i, j] = f(i, j); return a; }
	public static T[,,] MakeArray<T>(int n, int m, int l, Func<int, int, int, T> f) { var a = new T[n, m, l]; for (var i = 0; i < n; i++) for (var j = 0; j < m; j++) for (var k = 0; k < l; k++) a[i, j, k] = f(i, j, k); return a; }
	public static T[] Recurse<T>(int n, T a0, Func<int, T, T> f) { var a = new T[n]; a[0] = a0; for (var i = 1; i < n; i++) a[i] = f(i, a[i - 1]); return a; }
	public static T[] Accumulate<T>(IList<T> a, T zero, Func<T, T, T> f) { var s = new T[a.Count + 1]; s[0] = zero; for (var i = 0; i < a.Count; i++) s[i + 1] = f(s[i], a[i]); return s; }
	public static int FirstBinary(int min, int max, Predicate<int> pred)
	{
		while (min < max)
		{
			var mid = (min + max) / 2;
			if (pred(mid)) max = mid;
			else min = mid + 1;
		}
		return min;
	}
	public static long GCD(long a, long b)
	{
		var n = (ulong)Abs(a); var m = (ulong)Abs(b);
		if (n == 0) return (long)m; if (m == 0) return (long)n;
		int zm = 0, zn = 0;
		while ((n & 1) == 0) { n >>= 1; zn++; }
		while ((m & 1) == 0) { m >>= 1; zm++; }
		while (m != n)
		{
			if (m > n) { m -= n; while ((m & 1) == 0) m >>= 1; }
			else { n -= m; while ((n & 1) == 0) n >>= 1; }
		}
		return (long)n << Math.Min(zm, zn);
	}
	public static long Mod(long a, long mod) => (a % mod + mod) % mod;
	public static long Inverse(long a, long mod) => Mod(SolveLinear(Mod(a, mod), mod).x, mod);
	public static long Pow(long a, long b, long mod)
	{
		var p = 1L;
		var x = a;
		while (b > 0)
		{
			if ((b & 1) == 1) p = (p * x) % mod;
			b >>= 1;
			x = (x * x) % mod;
		}
		return p;
	}
	public static ulong Pow(ulong a, ulong b, ulong mod)
	{
		var p = 1uL;
		var x = a;
		while (b > 0)
		{
			if ((b & 1) == 1) p = (p * x) % mod;
			b >>= 1;
			x = (x * x) % mod;
		}
		return p;
	}
	// return (x, y) such that n * x + m * y == gcd(n, m)
	public static (long x, long y) SolveLinear(long n, long m)
	{
		var A = new long[,] { { n < 0 ? -1 : 1, 0 }, { 0, m < 0 ? -1 : 1 } };
		n = Abs(n); m = Abs(m);
		while (m > 0)
		{
			long q = n / m, r = n % m;
			(n, m) = (m, r);
			for (var i = 0; i < 2; i++) (A[i, 0], A[i, 1]) = (A[i, 1], A[i, 0] - q * A[i, 1]);
		}
		return (A[0, 0], A[1, 0]);
	}
	public static int CombineHashCodes(int h1, int h2) => (((h1 << 5) + h1) ^ h2);
	public static int[] GetFact(int lim, int mod)
	{
		var f = new int[lim];
		f[0] = 1;
		for (var i = 1; i < lim; i++) f[i] = (int)((long)f[i - 1] * i % mod);
		return f;
	}
	public static int[] GetInvFact(int lim, int mod)
	{
		var fc = 1;
		for (var i = 2; i < lim; i++) fc = (int)((long)fc * i % mod);
		return GetInvFact(lim, fc, mod);
	}
	// GetInvFact(n, (n-1)! mod p, p) gives {1, 1/2, ..., 1/(n-1)!} mod p
	public static int[] GetInvFact(int lim, int fc_of_lim_m_1, int mod)
	{
		var ifc = new int[lim];
		ifc[lim - 1] = (int)Inverse(fc_of_lim_m_1, mod);
		for (var i = lim - 1; i >= 1; i--) ifc[i - 1] = (int)((long)ifc[i] * i % mod);
		return ifc;
	}
	public static Comparison<T> DefaultComparison<T>() => (x, y) => Comparer<T>.Default.Compare(x, y);
	public static Comparison<T> ToComparison<T>(this IComparer<T>? comp) => comp switch { null => DefaultComparison<T>(), _ => (x, y) => comp.Compare(x, y) };
	public static bool Chmax<T>(ref T a, T b) where T : IComparable<T>
	{
		if (a.CompareTo(b) < 0)
		{
			a = b;
			return true;
		}
		return false;
	}
	public static bool Chmin<T>(ref T a, T b) where T : IComparable<T>
	{
		if (a.CompareTo(b) > 0)
		{
			a = b;
			return true;
		}
		return false;
	}
	public static void Swap<T>(this IList<T> array, int i, int j) => (array[i], array[j]) = (array[j], array[i]);
	public static void Swap<T>(ref T a, ref T b) => (a, b) = (b, a);
	public static void Shuffle<T>(IList<T> source, Random rand) { for (var i = source.Count - 1; i >= 0; --i) source.Swap(i, rand.Next(0, i + 1)); }
	public static double Min(params double[] nums) { var min = double.MaxValue; foreach (var n in nums) min = Math.Min(min, n); return min; }
	// get all primes less than or equal to n
	public static List<int> GetPrimes(int n)
	{
		if (n < 3) n = 3;
		var m = (n - 1) >> 1;
		var ps = new List<int>((int)(n / Log(n))) { 2 };
		var ng = new bool[m];
		for (var i = 0; i < m; i++)
		{
			if (!ng[i])
			{
				var p = 2 * i + 3;
				ps.Add(p);
				for (var k = 3 * i + 3; k < m; k += p) ng[k] = true;
			}
		}
		return ps;
	}
	public static long ChineseRemainder((long mod, long rem) mr1, (long mod, long rem) mr2)
	{
		var (m1, r1) = mr1;
		var (m2, r2) = mr2;
		var (x, y) = SolveLinear(m1, m2);
		return (m1 * x * r2 + m2 * y * r1) % (m1 * m2);
	}
	public static long ChineseRemainder(params (long mod, long rem)[] mrs)
	{
		if (mrs.Length == 0) return 0;
		if (mrs.Length == 1) return mrs[0].rem;
		if (mrs.Length == 2) return ChineseRemainder(mrs[0], mrs[1]);
		(long mod, long rem) t = (1, 0);
		for (var i = 0; i < mrs.Length; i++) t = (t.mod * mrs[i].mod, ChineseRemainder(t, mrs[i]));
		return t.rem;
	}
	public static bool IsPrime(ulong n)
	{
		if (n <= 1 || (n > 2 && n % 2 == 0)) return false;
		var test = new uint[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 111 };
		var d = n - 1;
		var s = 0;
		while (d % 2 == 0) { ++s; d /= 2; }
		bool f(ulong t)
		{
			var x = Pow(t, d, n);
			if (x == 1) return true;
			for (var r = 0L; r < s; r++)
			{
				if (x == n - 1) return true;
				x = x * x % n;
			}
			return false;
		};
		for (var i = 0; test[i] < n && test[i] != 111; i++) if (!f(test[i])) return false;
		return true;
	}
}
class PriorityQueue<T> : IEnumerable<T>, ICollection, IEnumerable, ICloneable
{
	readonly Comparison<T> comp;
	List<T> list;
	public int Count { get; private set; } = 0;
	public bool IsEmpty => Count == 0;
	public PriorityQueue(IEnumerable<T> source) : this((Comparison<T>?)null, 0, source) { }
	public PriorityQueue(int capacity = 4, IEnumerable<T>? source = null) : this((Comparison<T>?)null, capacity, source) { }
	public PriorityQueue(IComparer<T> comp, IEnumerable<T>? source) : this(comp.ToComparison(), source) { }
	public PriorityQueue(IComparer<T> comp, int capacity = 4, IEnumerable<T>? source = null) : this(comp.ToComparison(), source) => list.Capacity = capacity;
	public PriorityQueue(Comparison<T>? comp, IEnumerable<T>? source) : this(comp, 0, source) { }
	public PriorityQueue(Comparison<T>? comp, int capacity = 4, IEnumerable<T>? source = null) { this.comp = comp ?? DefaultComparison<T>(); list = new List<T>(capacity); if (source != null) foreach (var x in source) Enqueue(x); }
	/// <summary>
	/// add an item
	/// this is an O(log n) operation
	/// </summary>
	/// <param name="x">item</param>
	public void Enqueue(T x)
	{
		var pos = Count++;
		list.Add(x);
		while (pos > 0)
		{
			var p = (pos - 1) / 2;
			if (comp(list[p], x) <= 0) break;
			list[pos] = list[p];
			pos = p;
		}
		list[pos] = x;
	}
	/// <summary>
	/// return the minimum element and remove it
	/// this is an O(log n) operation
	/// </summary>
	/// <returns>the minimum</returns>
	public T Dequeue()
	{
		var value = list[0];
		var x = list[--Count];
		list.RemoveAt(Count);
		if (Count == 0) return value;
		var pos = 0;
		while (pos * 2 + 1 < Count)
		{
			var a = 2 * pos + 1;
			var b = 2 * pos + 2;
			if (b < Count && comp(list[b], list[a]) < 0) a = b;
			if (comp(list[a], x) >= 0) break;
			list[pos] = list[a];
			pos = a;
		}
		list[pos] = x;
		return value;
	}
	/// <summary>
	/// look at the minimum element
	/// this is an O(1) operation
	/// </summary>
	/// <returns>the minimum</returns>
	public T Peek() => list[0];
	public IEnumerator<T> GetEnumerator() { var x = (PriorityQueue<T>)Clone(); while (x.Count > 0) yield return x.Dequeue(); }
	void CopyTo(Array array, int index) { foreach (var x in this) array.SetValue(x, index++); }
	public object Clone() { var x = new PriorityQueue<T>(comp, Count) { Count = Count }; x.list.AddRange(list); return x; }
	public void Clear() { list = new List<T>(); Count = 0; }
	public void TrimExcess() => list.TrimExcess();
	/// <summary>
	/// check whether item is in this queue
	/// this is an O(n) operation
	/// </summary>
	public bool Contains(T item) => list.Contains(item);
	IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
	void ICollection.CopyTo(Array array, int index) => CopyTo(array, index);
	bool ICollection.IsSynchronized => false;
	object ICollection.SyncRoot => this;
}
class AVLTree<T> : IEnumerable<T>, ICollection<T>, ICollection, IEnumerable
{
	public class AVLNode : IEnumerable<T>
	{
		readonly AVLTree<T> tree;
		int height;
		public int Height => height;
		public int Bias => Left.height - Right.height;
		public T Item;
		public AVLNode? Parent;
		public AVLNode Left;
		public AVLNode Right;
		AVLNode(T x, AVLTree<T> tree) { this.tree = tree; Item = x; Left = tree.sentinel; Right = tree.sentinel; }
		public AVLNode(AVLTree<T> tree) : this(default!, tree) { height = 0; Parent = null; }
		public AVLNode(T x, AVLNode parent, AVLTree<T> tree) : this(x, tree) { height = 1; Parent = parent; }
		public void Adjust() => height = 1 + Math.Max(Left.height, Right.height);
		public void ResetAsSentinel() { height = 0; Left = tree.sentinel; Right = tree.sentinel; }
		public IEnumerator<T> GetEnumerator()
		{
			if (this != tree.sentinel)
			{
				foreach (var x in Left) yield return x;
				yield return Item;
				foreach (var x in Right) yield return x;
			}
		}
		public void SetLeft(AVLNode u) { Left = u; u.Parent = this; }
		public void SetRight(AVLNode u) { Right = u; u.Parent = this; }
		public void SetLR(bool is_left, AVLNode u) { if (is_left) SetLeft(u); else SetRight(u); }
		public bool IsLeftOfParent => Parent!.Left == this;
		IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
	}
	readonly AVLNode sentinel;
	readonly Comparison<T> comp;
	readonly Func<T, T, bool> equals;
	int count;
	// assumed to be comparer
	// i.e. comp(x,x)=0, and comp(x,y)>0 then comp(y,x)<0, and comp(x,y)>0 & comp(y,z)>0 then comp(x,z)>0
	public AVLTree(Comparison<T> comp)
	{
		sentinel = new AVLNode(this);
		sentinel.ResetAsSentinel();
		this.comp = comp ?? DefaultComparison<T>();
		if (typeof(T).IsValueType) equals = (x, y) => x!.Equals(y);
		else equals = (x, y) => ReferenceEquals(x, y);
		count = 0;
	}
	public AVLTree(IComparer<T>? comp = null) : this(comp.ToComparison()) { }
	// u must have non-null parent
	void Replace(AVLNode u, AVLNode v) => u.Parent!.SetLR(u.IsLeftOfParent, v);
	AVLNode RotateL(AVLNode v)
	{
		var u = v.Right;
		Replace(v, u);
		v.SetRight(u.Left);
		u.SetLeft(v);
		v.Adjust();
		u.Adjust();
		return u;
	}
	AVLNode RotateR(AVLNode u)
	{
		var v = u.Left;
		Replace(u, v);
		u.SetLeft(v.Right);
		v.SetRight(u);
		u.Adjust();
		v.Adjust();
		return v;
	}
	AVLNode RotateLR(AVLNode t) { RotateL(t.Left); return RotateR(t); }
	AVLNode RotateRL(AVLNode t) { RotateR(t.Right); return RotateL(t); }
	void Adjust(bool isInsertMode, AVLNode node)
	{
		while (node.Parent != sentinel)
		{
			var parent = node.Parent!;
			var height = parent.Height;
			if ((parent.Left == node) == isInsertMode)
				if (parent.Bias == 2) parent = parent.Left.Bias >= 0 ? RotateR(parent) : RotateLR(parent);
				else parent.Adjust();
			else
				if (parent.Bias == -2) parent = parent.Right.Bias <= 0 ? RotateL(parent) : RotateRL(parent);
			else parent.Adjust();
			if (height == parent.Height) break;
			node = parent;
		}
	}
	public void Add(T item)
	{
		var parent = sentinel;
		var pos = sentinel.Left;
		var isLeft = true;
		count++;
		while (pos != sentinel)
			if (comp(item, pos.Item) < 0) { parent = pos; pos = pos.Left; isLeft = true; }
			else { parent = pos; pos = pos.Right; isLeft = false; }
		if (isLeft)
			Adjust(true, parent.Left = new AVLNode(item, parent, this));
		else
			Adjust(true, parent.Right = new AVLNode(item, parent, this));
	}
	// if equals(x,y) holds then !(comp(x,y)<0) and !(comp(x,y)>0) must hold
	// i.e. equals(x,y) -> comp(x,y)=0
	public bool Remove(T item, AVLNode start)
	{
		var pos = start;
		while (pos != sentinel)
		{
			if (comp(item, pos.Item) < 0) pos = pos.Left;
			else if (comp(item, pos.Item) > 0) pos = pos.Right;
			else if (equals(pos.Item, item))
			{
				if (pos.Left == sentinel)
				{
					Replace(pos, pos.Right);
					Adjust(false, pos.Right);
				}
				else
				{
					var max = Max(pos.Left);
					pos.Item = max.Item;
					Replace(max, max.Left);
					Adjust(false, max.Left);
				}
				count--;
				return true;
			}
			else return Remove(item, pos.Left) || Remove(item, pos.Right);
		}
		return false;
	}
	public bool Remove(T item) => Remove(item, sentinel.Left);
	AVLNode Max(AVLNode node)
	{
		while (node.Right != sentinel) node = node.Right;
		return node;
	}
	AVLNode Min(AVLNode node)
	{
		while (node.Left != sentinel) node = node.Left;
		return node;
	}
	public bool Contains(T item)
	{
		var pos = sentinel.Left;
		while (pos != sentinel)
		{
			if (comp(item, pos.Item) < 0) pos = pos.Left;
			else if (comp(item, pos.Item) > 0) pos = pos.Right;
			else return true;
		}
		return false;
	}
	public T Find(T item)
	{
		var pos = sentinel.Left;
		while (pos != sentinel)
		{
			if (comp(item, pos.Item) < 0) pos = pos.Left;
			else if (comp(item, pos.Item) > 0) pos = pos.Right;
			else return pos.Item;
		}
		return default!;
	}
	public AVLNode? LowerBound(Predicate<T> pred) { LowerBound(pred, sentinel.Left, out var node); return node; }
	public AVLNode? UpperBound(Predicate<T> pred) { UpperBound(pred, sentinel.Left, out var node); return node; }
	public AVLNode? LowerBound(T item) => LowerBound(x => comp(x, item) >= 0);
	public AVLNode? UpperBound(T item) => UpperBound(x => comp(x, item) <= 0);
	bool UpperBound(Predicate<T> pred, AVLNode node, out AVLNode? res)
	{
		if (node == sentinel) { res = null; return false; }
		if (pred(node.Item)) { if (!UpperBound(pred, node.Right, out res)) res = node; return true; }
		else return UpperBound(pred, node.Left, out res);
	}
	bool LowerBound(Predicate<T> pred, AVLNode node, out AVLNode? res)
	{
		if (node == sentinel) { res = null; return false; }
		if (pred(node.Item)) { if (!LowerBound(pred, node.Left, out res)) res = node; return true; }
		else return LowerBound(pred, node.Right, out res);
	}
	public T Min() => Min(sentinel.Left).Item;
	public AVLNode MinNode() => Min(sentinel.Left);
	public T Max() => Max(sentinel.Left).Item;
	public AVLNode MaxNode() => Max(sentinel.Left);
	public bool IsEmpty => sentinel.Left == sentinel;
	public void Clear() { sentinel.Left = sentinel; count = 0; sentinel.ResetAsSentinel(); }
	public IEnumerator<T> GetEnumerator() => sentinel.Left.GetEnumerator();
	IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
	public void CopyTo(T[] array, int arrayIndex) { foreach (var x in this) array[arrayIndex++] = x; }
	public int Count => count;
	public bool IsReadOnly => true;
	public void CopyTo(Array array, int index) { foreach (var x in this) array.SetValue(x, index++); }
	public bool IsSynchronized => false;
	public object SyncRoot => this;
}