#![allow(dead_code)]
use crate::scanner::Scanner;
use crate::vec::IterLikeVec;
use std::collections::HashSet;
fn main() {
    let mut scan = Scanner::new();
    let n = scan.read::<usize>();
    let s = scan.readn::<String>(n).to::<HashSet<_>>();
    println!("{}", s.len());
}
mod vec {
    use std::iter::{FromIterator, Sum};
    pub trait IterLikeVec<T> {
        fn map<B, F>(&self, f: F) -> Vec<B>
        where
            F: FnMut(T) -> B;
        fn filter<P>(&self, predicate: P) -> Vec<T>
        where
            P: FnMut(&T) -> bool;
        fn filter_map<B, F>(&self, f: F) -> Vec<B>
        where
            F: FnMut(T) -> Option<B>;
        fn any<P>(&self, predicate: P) -> bool
        where
            P: FnMut(&T) -> bool;
        fn all<P>(&self, predicate: P) -> bool
        where
            P: FnMut(&T) -> bool;
        fn sum<S>(&self) -> S
        where
            S: Sum<T>;
        fn enumerate(&self) -> Vec<(usize, T)>;
        fn to<B: FromIterator<T>>(&self) -> B;
    }
    impl<T: Clone> IterLikeVec<T> for Vec<T> {
        fn map<B, F>(&self, f: F) -> Vec<B>
        where
            F: FnMut(T) -> B,
        {
            self.iter().cloned().map(f).collect()
        }
        fn filter<P>(&self, predicate: P) -> Vec<T>
        where
            P: FnMut(&T) -> bool,
        {
            self.iter().cloned().filter(predicate).collect()
        }
        fn filter_map<B, F>(&self, f: F) -> Vec<B>
        where
            F: FnMut(T) -> Option<B>,
        {
            self.iter().cloned().filter_map(f).collect()
        }
        fn any<P>(&self, predicate: P) -> bool
        where
            P: FnMut(&T) -> bool,
        {
            self.iter().any(predicate)
        }
        fn all<P>(&self, predicate: P) -> bool
        where
            P: FnMut(&T) -> bool,
        {
            self.iter().all(predicate)
        }
        fn sum<S>(&self) -> S
        where
            S: Sum<T>,
        {
            Sum::sum(self.iter().cloned())
        }
        fn enumerate(&self) -> Vec<(usize, T)> {
            self.iter().cloned().enumerate().collect()
        }
        fn to<B: FromIterator<T>>(&self) -> B {
            self.iter().cloned().collect()
        }
    }
}
mod scanner {
    use std::io::{stdin, BufReader, Bytes, Read, Stdin};
    use std::str::FromStr;
    pub struct Scanner {
        buf: Bytes<BufReader<Stdin>>,
    }
    impl Scanner {
        pub fn new() -> Scanner {
            Scanner {
                buf: BufReader::new(stdin()).bytes(),
            }
        }
        pub fn read_next<T: FromStr>(&mut self) -> Option<T> {
            let token = self
                .buf
                .by_ref()
                .map(|c| c.unwrap() as char)
                .skip_while(|c| c.is_whitespace())
                .take_while(|c| !c.is_whitespace())
                .collect::<String>();
            token.parse::<T>().ok()
        }
        pub fn read<T: FromStr>(&mut self) -> T {
            self.read_next().unwrap()
        }
        pub fn readn<T: FromStr>(&mut self, n: usize) -> Vec<T> {
            (0..n).map(|_| self.read::<T>()).collect()
        }
        pub fn chars(&mut self) -> Vec<char> {
            self.read::<String>().chars().collect()
        }
        pub fn char(&mut self) -> char {
            self.read::<String>().chars().next().unwrap()
        }
    }
}



Measured memory_bytes: 25496