Skip to content
Related Articles

Related Articles

Implement Undo and Redo features of a Text Editor
  • Last Updated : 18 Mar, 2021

Given an array of strings Q[], consisting of queries of the following types:

  • “WRITE X”: Write a character X into the document.
  • “UNDO”: Erases the last change made to the document.
  • “REDO”: Restores the most recent UNDO operation performed on the document.
  • “READ”: Reads and prints the contents of the documents.

Examples:

Input: Q = {“WRITE A”, “WRITE B”, “WRITE C”, “UNDO”, “READ”, “REDO”, “READ”}
Output: AB ABC
Explanation: 
Perform “WRITE A” on the document. Therefore, the document contains only “A”.
Perform “WRITE B” on the document. Therefore, the document contains “AB”.
Perform “WRITE C” on the document. Therefore, the document contains “ABC”.
Perform “UNDO” on the document. Therefore, the document contains “AB”.
Print the contents of the document, i.e. “AB”
Perform “REDO” on the document. Therefore, the document contains “ABC”.
Print the contents of the document, i.e. “ABC”

Input: Q = {“WRITE x”, “WRITE y”, “UNDO”, “WRITE z”, “READ”, “REDO”, “READ”}
Output:xz xzy

Approach: The problem can be solved using Stack. Follow the steps below to solve the problem:



Below is the implementation of the above approach:

C++




// C++ Program to implement
// the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to perform
// "WRITE X" operation
void WRITE(stack<char>& Undo,
           char X)
{
    // Push an element to
    // the top of stack
    Undo.push(X);
}
 
// Function to perform
// "UNDO" operation
void UNDO(stack<char>& Undo,
          stack<char>& Redo)
{
    // Stores top element
    // of the stack
    char X = Undo.top();
 
    // Erase top element
    // of the stack
    Undo.pop();
 
    // Push an element to
    // the top of stack
    Redo.push(X);
}
 
// Function to perform
// "REDO" operation
void REDO(stack<char>& Undo,
          stack<char>& Redo)
{
    // Stores the top element
    // of the stack
    char X = Redo.top();
 
    // Erase the top element
    // of the stack
    Redo.pop();
 
    // Push an element to
    // the top of the stack
    Undo.push(X);
}
 
// Function to perform
// "READ" operation
void READ(stack<char> Undo)
{
    // Store elements of stack
    // in reverse order
    stack<char> revOrder;
 
    // Traverse Undo stack
    while (!Undo.empty()) {
        // Push an element to
        // the top of stack
        revOrder.push(Undo.top());
 
        // Erase top element
        // of stack
        Undo.pop();
    }
 
    while (!revOrder.empty()) {
        // Print the top element
        // of the stack
        cout << revOrder.top();
      Undo.push(revOrder.top());
 
        // Erase the top element
        // of the stack
        revOrder.pop();
    }
 
    cout << " ";
}
 
// Function to perform the
// queries on the document
void QUERY(vector<string> Q)
{
    // Stores the history of all
    // the queries that have been
    // processed on the document
    stack<char> Undo;
 
    // Stores the elements
    // of REDO query
    stack<char> Redo;
 
    // Stores total count
    // of queries
    int N = Q.size();
 
    // Traverse all the query
    for (int i = 0; i < N; i++) {
        if (Q[i] == "UNDO") {
            UNDO(Undo, Redo);
        }
        else if (Q[i] == "REDO") {
            REDO(Undo, Redo);
        }
        else if (Q[i] == "READ") {
            READ(Undo);
        }
        else {
            WRITE(Undo, Q[i][6]);
        }
    }
}
 
// Driver Code
int main()
{
 
    vector<string> Q = { "WRITE A", "WRITE B",
                         "WRITE C", "UNDO",
                         "READ", "REDO", "READ" };
    QUERY(Q);
    return 0;
}

Python3




# Python Program to implement
# the above approach
global Undo
global Redo
 
# Stores the history of all
# the queries that have been
# processed on the document
Undo = []
 
# Stores the elements
# of REDO query
Redo = []
 
# Function to perform
# "WRITE X" operation
def WRITE(Undo, X):
 
    # Push an element to
    # the top of stack
    Undo.append(X)
 
# Function to perform
# "UNDO" operation
def UNDO(Undo, Redo):
 
    # Stores top element
    # of the stack
    X = Undo[-1]
 
    # Erase top element
    # of the stack
    Undo.pop()
 
    # Push an element to
    # the top of stack
    Redo.append(X)
 
# Function to perform
# "REDO" operation
def REDO(Undo, Redo):
 
    # Stores the top element
    # of the stack
    X = Redo[-1]
 
    # Erase the top element
    # of the stack
    Redo.pop()
 
    # Push an element to
    # the top of the stack
    Undo.append(X)
 
# Function to perform
# "READ" operation
def READ(Undo):
    print(*Undo, sep = "",
          end = " ")
 
# Function to perform the
# queries on the document
def QUERY(Q):
 
    # Stores total count
    # of queries
    N = len(Q)
 
    # Traverse all the query
    for i in range(N):
        if(Q[i] == "UNDO"):
            UNDO(Undo, Redo)
        elif(Q[i] == "REDO"):
            REDO(Undo, Redo)
        elif(Q[i] == "READ"):
            READ(Undo)
        else:
            WRITE(Undo, Q[i][6])
 
# Driver Code
Q = ["WRITE A", "WRITE B", "WRITE C",
     "UNDO", "READ", "REDO", "READ"]
QUERY(Q)
 
#This code is contributed by avanitrachhadiya2155
Output: 
AB ABC

 

Time Complexity:
UNDO: O(1)
REDO: O(1)
WRITE: O(1)
READ: (N), where N denotes the size of the Undo stack
Auxiliary Space: O(N)

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

My Personal Notes arrow_drop_up
Recommended Articles
Page :