use std::collections::{BTreeMap, BTreeSet};
fn main() {
    let s = std::io::stdin();
    let mut sc = Scanner { stdin: s.lock() };
    let n: usize = sc.read();
    let q: usize = sc.read();
    let s = sc.chars();
    let td: Vec<(char, bool)> = (0..q)
        .map(|_| {
            (
                sc.read::<String>().chars().next().unwrap(),
                sc.read::<String>().chars().next().unwrap() == 'R',
            )
        })
        .collect();
    let mut state: BTreeMap<char, BTreeSet<(usize, usize)>> = BTreeMap::new();
    for &(t, is_right) in td.iter().rev() {
        if let Some(removed_set) = state.remove(&t) {
            for (cur, hit) in removed_set.into_iter() {
                if hit + 1 == cur {
                    if is_right {
                        // hit
                        if hit + 1 < n {
                            state
                                .entry(s[hit + 1])
                                .or_insert(BTreeSet::new())
                                .insert((hit, hit + 1));
                        }
                        if hit > 0 {
                            state
                                .entry(s[hit - 1])
                                .or_insert(BTreeSet::new())
                                .insert((hit, hit - 1));
                        }
                    } else {
                        // not hit
                        state
                            .entry(s[cur - 1])
                            .or_insert(BTreeSet::new())
                            .insert((cur, cur - 1));
                    }
                } else if cur + 1 == hit {
                    if is_right {
                        // not hit
                        state
                            .entry(s[cur + 1])
                            .or_insert(BTreeSet::new())
                            .insert((cur, cur + 1));
                    } else {
                        // hit
                        if hit + 1 < n {
                            state
                                .entry(s[hit + 1])
                                .or_insert(BTreeSet::new())
                                .insert((hit, hit + 1));
                        }
                        if hit > 0 {
                            state
                                .entry(s[hit - 1])
                                .or_insert(BTreeSet::new())
                                .insert((hit, hit - 1));
                        }
                    }
                } else {
                    unreachable!()
                }
            }
        }

        if is_right && t == s[n - 1] {
            state
                .entry(s[n - 2])
                .or_insert(BTreeSet::new())
                .insert((n - 1, n - 2));
        } else if !is_right && t == s[0] {
            state.entry(s[1]).or_insert(BTreeSet::new()).insert((0, 1));
        }
    }

    let mut map = BTreeMap::new();
    for (_, set) in state.into_iter() {
        for (cur, _) in set.into_iter() {
            map.entry(s[cur]).or_insert(BTreeSet::new()).insert(cur);
        }
    }
    let mut alive = vec![1; n];
    for &(t, is_right) in td.iter() {
        if let Some(removed) = map.remove(&t) {
            if is_right {
                for i in removed.into_iter().rev() {
                    if i < n - 1 {
                        alive[i + 1] += alive[i];
                        map.entry(s[i + 1]).or_insert(BTreeSet::new()).insert(i + 1);
                    }
                    alive[i] = 0;
                }
            } else {
                for i in removed.into_iter() {
                    if i > 0 {
                        alive[i - 1] += alive[i];
                        map.entry(s[i - 1]).or_insert(BTreeSet::new()).insert(i - 1);
                    }
                    alive[i] = 0;
                }
            }
        }
    }

    let remain: usize = alive.into_iter().sum();
    println!("{}", remain);
}

pub struct Scanner<R> {
    stdin: R,
}

impl<R: std::io::Read> Scanner<R> {
    pub fn read<T: std::str::FromStr>(&mut self) -> T {
        use std::io::Read;
        let buf = self
            .stdin
            .by_ref()
            .bytes()
            .map(|b| b.unwrap())
            .skip_while(|&b| b == b' ' || b == b'\n' || b == b'\r')
            .take_while(|&b| b != b' ' && b != b'\n' && b != b'\r')
            .collect::<Vec<_>>();
        unsafe { std::str::from_utf8_unchecked(&buf) }
            .parse()
            .ok()
            .expect("Parse error.")
    }
    pub fn vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.read()).collect()
    }
    pub fn chars(&mut self) -> Vec<char> {
        self.read::<String>().chars().collect()
    }
}
