#[allow(unused_imports)]
use std::cmp::{max, min, Ordering};
#[allow(unused_imports)]
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
#[allow(unused_imports)]
use std::iter::FromIterator;
#[allow(unused_imports)]
use std::io::stdin;

mod util {
    use std::io::stdin;
    use std::str::FromStr;
    use std::fmt::Debug;

    #[allow(dead_code)]
    pub fn line() -> String {
        let mut line: String = String::new();
        stdin().read_line(&mut line).unwrap();
        line.trim().to_string()
    }

    #[allow(dead_code)]
    pub fn gets<T: FromStr>() -> Vec<T>
    where
        <T as FromStr>::Err: Debug,
    {
        let mut line: String = String::new();
        stdin().read_line(&mut line).unwrap();
        line.split_whitespace()
            .map(|t| t.parse().unwrap())
            .collect()
    }
}

#[allow(unused_macros)]
macro_rules! get {
    ($t:ty) => {
        {
            let mut line: String = String::new();
            stdin().read_line(&mut line).unwrap();
            line.trim().parse::<$t>().unwrap()
        }
    };
    ($($t:ty),*) => {
        {
            let mut line: String = String::new();
            stdin().read_line(&mut line).unwrap();
            let mut iter = line.split_whitespace();
            (
                $(iter.next().unwrap().parse::<$t>().unwrap(),)*
            )
        }
    };
    ($t:ty; $n:expr) => {
        (0..$n).map(|_|
                    get!($t)
                   ).collect::<Vec<_>>()
    };
    ($($t:ty),*; $n:expr) => {
        (0..$n).map(|_|
                    get!($($t),*)
                   ).collect::<Vec<_>>()
    };
    ($t:ty ;;) => {
        {
            let mut line: String = String::new();
            stdin().read_line(&mut line).unwrap();
            line.split_whitespace()
                .map(|t| t.parse::<$t>().unwrap())
                .collect::<Vec<_>>()
        }
    };
}

#[allow(unused_macros)]
macro_rules! debug {
    ($($a:expr),*) => {
        println!(concat!($(stringify!($a), " = {:?}, "),*), $($a),*);
    }
}

struct Trie {
    left: Option<Box<Trie>>,
    right: Option<Box<Trie>>,
}

impl Trie {
    fn new() -> Trie {
        Trie {
            left: None,
            right: None,
        }
    }

    fn add(&mut self, s: &[char]) {
        if s.is_empty() {
        } else if s[0] == '0' {
            if self.left.is_none() {
                self.left = Some(Box::new(Trie::new()));
            }
            self.left.as_mut().unwrap().add(&s[1..]);
        } else {
            if self.right.is_none() {
                self.right = Some(Box::new(Trie::new()));
            }
            self.right.as_mut().unwrap().add(&s[1..]);
        }
    }

    fn tails(&self, depth: usize, res: &mut Vec<bool>) {
        if let Some(ref l) = self.left {
            l.tails(depth + 1, res);
        } else {
            res[depth] = !res[depth];
        }

        if let Some(ref r) = self.right {
            r.tails(depth + 1, res);
        } else {
            res[depth] = !res[depth];
        }
    }
}

fn main() {
    let (n, l) = get!(usize, i64);
    let ss = get!(String; n);

    let mut trie = Trie::new();
    let mut max_len = 0;

    for s in &ss {
        let v = s.chars().collect::<Vec<_>>();
        trie.add(&v);
        max_len = max(max_len, v.len());
    }

    // debug!(trie.tails());
    let mut v = vec![false; max_len + 1];
    trie.tails(0, &mut v);

    if v.iter()
        .enumerate()
        .filter_map(|(i, &b)| if b { Some(i) } else { None })
        .map(|d| l - d as i64)
        .map(|x| x & -x)
        .fold(0, |a, b| a ^ b) == 0
    {
        println!("Bob");
    } else {
        println!("Alice");
    }
}


Measured memory_bytes: 7932