use std::io::{BufRead, BufWriter, Write};
use std::collections::HashMap;

fn main() {
    let stdin = std::io::stdin();
    let stdout = std::io::stdout();
    solve(&mut stdin.lock(), &mut BufWriter::new(stdout.lock()));
}

fn solve<R: BufRead, W: Write>(stdin: &mut R, stdout: &mut BufWriter<W>) {
    let (n, q): (usize, usize) = stdin.gets().split(' ').values();
    let map = stdin.gets().into_bytes();
    let mut pos = vec![HashMap::new(); 26];
    for i in 0..n {
        let al = (map[i] - b'A') as usize;
        pos[al].insert(i, 1);
    }
    let mut dropped = 0;
    for line in stdin.lines().take(q).map(|x| x.unwrap().into_bytes()) {
        let (t, d) = ((line[0] - b'A') as usize, line[2]);
        let mut cur = HashMap::new();
        std::mem::swap(&mut pos[t], &mut cur);
        for (&p, &num) in &cur {
            let nbr = match d {
                b'R' => {
                    if p == n - 1 {
                        dropped += num;
                        continue;
                    }
                    p + 1
                },
                b'L' => {
                    if p == 0 {
                        dropped += num;
                        continue;
                    }
                    p - 1
                },
                _ => panic!("Invalid input"),
            };
            let al = (map[nbr] - b'A') as usize;
            *pos[al].entry(nbr).or_insert(0) += num;
        }
    }
    writeln!(stdout, "{}", n - dropped).unwrap();
}

trait Gets { fn gets(&mut self) -> String; }
impl<T: std::io::BufRead> Gets for T {
    fn gets(&mut self) -> String { self.lines().next().unwrap().unwrap() } }

trait Values<T> { fn values(&mut self) -> T; }
impl<'a, I, T1, T2> Values<(T1, T2)> for I
    where I: Iterator<Item=&'a str>,
          T1: std::str::FromStr, T1::Err: std::fmt::Debug,
          T2: std::str::FromStr, T2::Err: std::fmt::Debug {
    fn values(&mut self) -> (T1, T2) {
        (self.next().unwrap().parse().unwrap(),
         self.next().unwrap().parse().unwrap())
    }
}
