public HashSet<ArrayList<String>> First(int k, String a){
       
        if(m_lastFirstK==k && m_allFirstK!=null){
            return m_allFirstK.get(a);
        }
        
        if(m_terminals.contains(a)){
             HashSet<ArrayList<String>> res = new HashSet<ArrayList<String>>();
            ArrayList<String> resList = new ArrayList<String>();
            resList.add(a);
            res.add(resList);
            return res;
        }
        
        HashMap<String,HashSet<ArrayList<String>>> table = new HashMap<String,HashSet<ArrayList<String>>>();
        HashMap<String,HashSet<ArrayList<String>>> prevTable = new HashMap<String,HashSet<ArrayList<String>>>();
        
        for(String nt : m_nonterminals){
            table.put(nt, new HashSet<ArrayList<String>>());
            prevTable.put(nt, new HashSet<ArrayList<String>>());
        }
        for(String t : m_terminals){
            HashSet<ArrayList<String>> set = new HashSet<ArrayList<String>>();
            ArrayList<String> list = new ArrayList<String>();
            list.add(t);
            set.add(list);
            table.put(t, set);
            prevTable.put(t, new HashSet<ArrayList<String>>());
        }
        
        while(!Helpers.tablesAreEquals(table, prevTable)){
            prevTable = copyTable(table);
            
            for(Rule rule : m_rules){
                String leftPart = rule.GetLeftPart();
                ArrayList<String> rightPart = rule.GetRightPart();
                HashSet<ArrayList<String>> curFirst = new HashSet<ArrayList<String>>();
                curFirst = prevTable.get(rightPart.get(0));
                for(int i=1;i<rightPart.size();i++){
                    curFirst = Helpers.plusK(curFirst, prevTable.get(rightPart.get(i)), k);
                }
                HashSet<ArrayList<String>> m = table.get(leftPart);
                m.addAll(curFirst);
                table.put(leftPart, m);
            }
        }
        m_allFirstK = table;
        return table.get(a);
    }