use std::ops::DivAssign;
use std::ops::MulAssign;
use std::ops::SubAssign;
use std::collections::BinaryHeap;
use std::str::FromStr;
use std::collections::HashSet;
use std::collections::BTreeMap;
use std::fmt::Display;
use std::ops::Neg;
use std::ops::Div;
use std::ops::Mul;
use std::ops::Add;
use std::ops::{AddAssign, Sub};
use std::cmp::max;
use std::collections::VecDeque;
use std::cmp::min;
use std::collections::{HashMap, BTreeSet};
use std::cmp::Ordering;
use std::fmt::Debug;

fn read_line() -> String {
    let mut buffer = String::new();
    std::io::stdin().read_line(&mut buffer).expect("No Line");
    buffer.trim().to_owned()
}
fn read_lines<T: std::str::FromStr>(count: usize) -> Vec<T> {
    let mut buffer = String::new();
    let mut vec = Vec::with_capacity(count);
    for _ in 0 .. count {
        std::io::stdin().read_line(&mut buffer).expect("No Line");
        vec.push(buffer.trim().parse().ok().expect("Can't Parse"));
        buffer.clear();
    }
    vec
}
fn read_tabulate<R, T: Fn(&str)->R> (count: usize, transformer: T) -> Vec<R> {
    let mut buffer = String::new();
    let mut vec = Vec::with_capacity(count);
    for _ in 0 .. count {
        std::io::stdin().read_line(&mut buffer).expect("No Line");
        vec.push(transformer(buffer.trim()));
        buffer.clear();
    }
    vec
}
fn read_value<T: std::str::FromStr>() -> T {
    read_line().trim().parse().ok().unwrap()
}
fn read_values<T: std::str::FromStr>() -> Vec<T> {
    read_line().trim().split_whitespace().map(|x| x.parse().ok().expect("Can't Parse")).collect::<Vec<T>>()
}
macro_rules! freeze {
    ($($id:ident), *) => {
        $(let $id = $id;)*
    };
}
macro_rules! read_map {
    ($ident: ident: [$block: block; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$block: block; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
}
macro_rules! read {
    (mut $ident: ident: [$ty:ty]) => {
        let mut $ident = read_values::<$ty>();
    };
    ($ident: ident: [$ty:ty]) => {
        let $ident = read_values::<$ty>();
    };
    (mut $ident: ident: [[$ty:ty]; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| read_values::<$ty>()).collect::<Vec<_>>();
    };
    ($ident: ident: [[$ty:ty]; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| read_values::<$ty>()).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$ty:ty; $size:expr]) => {
        let mut $ident = read_lines::<$ty>($size);
    };
    ($ident: ident: [$ty:ty; $size:expr]) => {
        let $ident = read_lines::<$ty>($size);
    };
    ($ident: ident: [$block: block; $size: expr]) => {
        let $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    (mut $ident: ident: [$block: block; $size: expr]) => {
        let mut $ident = (0 .. $size).into_iter().map(|_| $block).collect::<Vec<_>>();
    };
    ($($token: tt)*) => {
        let mut iter = read_values::<String>().into_iter();
        read_from_iter!(iter; $($token)*);
    };
}
macro_rules! read_from_iter {
    ($iter:expr; mut $ident:ident:$ty:ty, $($rest:tt)*) => {
        let mut $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
        read_from_iter!($iter; $($rest)*);
    };
    ($iter:expr; $ident:ident:$ty:ty, $($rest:tt)*) => {
        let $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
        read_from_iter!($iter; $($rest)*);
    };
    ($iter:expr; mut $ident:ident:$ty:ty) => {
        let mut $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
    };
    ($iter:expr; $ident:ident:$ty:ty) => {
        let $ident = $iter.next().unwrap().parse::<$ty>().expect("Can't Parse");
    };
    ($iter: expr; ) => {};
}
struct KeyValue<K, V> {
    key: K,
    value: V
}
impl <K: PartialOrd, V> PartialEq for KeyValue<K, V> {
    fn eq(&self, other: &Self) -> bool {
        self.key.eq(&other.key)
    }
}
impl <K: PartialOrd, V> Eq for KeyValue<K, V> {}
impl <K: PartialOrd, V> PartialOrd for KeyValue<K, V> {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        self.key.partial_cmp(&other.key)
    }
}
impl <K: PartialOrd, V> Ord for KeyValue<K, V> {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.key.partial_cmp(&other.key).ok_or("Can't Compare").unwrap()
    }
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
struct Point {
    x: i32, y: i32, z: i32
}
impl Add for Point {
    type Output = Point;
    fn add(self, rhs: Point) -> <Self as std::ops::Add<Point>>::Output { 
        Point{x: self.x + rhs.x, y: self.y + rhs.y, z: self.z + rhs.z}    
    }
}
impl Sub for Point {
    type Output = Point;
    fn sub(self, rhs: Point) -> <Self as std::ops::Sub<Point>>::Output { 
        Point{x: self.x - rhs.x, y: self.y - rhs.y, z: self.z - rhs.z}
    }
}
impl Point {
    fn rotate_by_x(&self) -> Point {
        Point{x: self.x, y: -self.z, z: self.y}
    }
    fn rotate_by_y(&self) -> Point {
        Point{x: self.z, y: self.y, z: -self.x}
    }
    fn rotate_by_z(&self) -> Point {
        Point{x: -self.y, y: self.x, z: self.z}
    }
}
#[derive(Copy, Clone, Debug)]
enum Token {
    Label(usize),
    Diff(Point),
}
impl FromStr for Token {
    type Err = ();
    fn from_str(s: &str) -> std::result::Result<Self, <Self as std::str::FromStr>::Err> { 
        match s {
            "+x" => Ok(Token::Diff(Point{x: 1, y: 0, z: 0})),
            "-x" => Ok(Token::Diff(Point{x: -1, y: 0, z: 0})),
            "+y" => Ok(Token::Diff(Point{x: 0, y: 1, z: 0})),
            "-y" => Ok(Token::Diff(Point{x: 0, y: -1, z: 0})),
            "+z" => Ok(Token::Diff(Point{x: 0, y: 0, z: 1})),
            "-z" => Ok(Token::Diff(Point{x: 0, y: 0, z: -1})),
            _ => if let Ok(label) = s.parse::<usize>() {
                Ok(Token::Label(label))
            }else {
                Err(())
            }
        }
     }
}

struct Key {
    bars: BTreeSet<(Point, Point)>,
    labeled: BTreeMap<usize, Point>,
    last: Point
}
impl Key {
    fn new() -> Key {
        Key{bars: BTreeSet::new(), labeled: BTreeMap::new(), last: Point{x: 0, y: 0, z: 0}}
    }
    fn add_bar(&mut self, token: Token) {
        match token {
            Token::Label(label) => {
                if let &Some(&last) = &self.labeled.get(&label) {
                    self.last = last;
                }else {
                    self.labeled.insert(label, self.last);
                }
            },
            Token::Diff(diff) => {
                let next = self.last + diff;
                self.bars.insert((min(self.last, next), max(self.last, next)));
                self.last = next
            }
        }
    }
    fn is_same(&self, other: &Key) -> bool {
        let self_suspects = self.suspects();
        let other_normalized = Key::normalize(&other.bars.iter().cloned().collect());
        self_suspects.into_iter().any(|bar| bar.len() == other_normalized.len() && (0 .. bar.len()).all(|i| bar[i] == other_normalized[i]))
    }
    fn suspects(&self) -> Vec<Vec<(Point, Point)>> {
        let mut bars = vec![self.bars.iter().cloned().collect::<Vec<_>>()];
        for i in 0 .. 5 {
            let rotated = if i & 1 == 0 {
                bars[i].iter().map(|&(a, b)| (a.rotate_by_x(), b.rotate_by_x())).collect::<Vec<_>>()
            }else {
                bars[i].iter().map(|&(a, b)| (a.rotate_by_z(), b.rotate_by_z())).collect::<Vec<_>>()
            };
            bars.push(rotated);
        }
        bars.into_iter().flat_map(|bar| {
            let mut ret = vec![Key::normalize(&bar)];
            for i in 0 .. 3 {
                let last = Key::normalize(&ret[i].iter().map(|&(a, b)| (a.rotate_by_y(), b.rotate_by_y())).collect());
                ret.push(last);
            }
            ret
        }).collect::<Vec<_>>()
    }
    fn normalize(bars: &Vec<(Point, Point)>) -> Vec<(Point, Point)> {
        let mut bar = bars.clone();
        let origin = bar.iter().flat_map(|&(a, b)| vec![a, b]).min().unwrap();
        for i in 0 .. bar.len() {
            let a = bar[i].0 - origin;
            let b = bar[i].1 - origin;
            bar[i] = (min(a, b), max(a, b));
        }
        bar.sort();
        bar
    }
}

fn main() {
    loop {
        let mut line1 = Vec::new();
        while line1.is_empty() {
            read!(line: [String]);
            line1 = line;
        }
        let a = line1[0].parse::<usize>().ok().unwrap();
        if a == 0 {break;}
        let mut first = line1[1..].iter().map(|s| s.parse::<Token>().ok().unwrap()).collect::<Vec<_>>();
        while first.len() < a {
            read!(tokens: [Token]);
            for t in tokens {
                first.push(t);
            }
        }
        read!(line2: [String]);
        let b = line2[0].parse::<usize>().ok().unwrap();
        let mut second = line2[1..].iter().map(|s| s.parse::<Token>().ok().unwrap()).collect::<Vec<_>>();
        while second.len() < b {
            read!(tokens: [Token]);
            for t in tokens {
                second.push(t);
            }
        }
        let mut first_key = Key::new();
        for token in first {
            first_key.add_bar(token);
        }
        let mut second_key = Key::new();
        for token in second {
            second_key.add_bar(token);
        }
        if first_key.is_same(&second_key) {
            println!("SAME");
        }else {
            println!("DIFFERENT");
        }
    }
}


Measured memory_bytes: 5072