Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* package whatever; // don't place package name! */
- import java.util.*;
- import java.lang.*;
- import java.io.*;
- /* Name of the class has to be "Main" only if the class is public. */
- class Main
- {
- public static void main (String[] args) throws java.lang.Exception
- {
- Scanner sc = new Scanner(System.in);
- int a = sc.nextInt();
- int s = sc.nextInt();
- Set<Integer> S = new HashSet();
- for(int i = 0 ; i < s ; ++i)S.add(i);
- int s0 = sc.nextInt();
- --s0;
- int sz_f = sc.nextInt();
- Set<Integer> F = new HashSet();
- for(int i = 0 ; i < sz_f ; ++i){
- int t = sc.nextInt();
- --t;
- F.add(t);
- }
- Map<Pair<Integer , Character> , ArrayList<Integer>> f = new HashMap();
- int k = sc.nextInt();
- while(k-->0){
- int u = sc.nextInt();
- char ch = sc.next().charAt(0);
- int v = sc.nextInt();
- --u;
- --v;
- Pair<Integer , Character> fnd = new Pair<Integer , Character>(u , ch);
- if(!f.containsKey(fnd)){
- // System.out.println("fdsfsd");
- f.put(fnd, new ArrayList<Integer>());
- }
- ArrayList<Integer> tmp = f.get(fnd);
- //tmp.add(v);
- tmp.add(v);
- f.put(fnd, tmp);
- }
- Automata<Integer> aut = new Automata<Integer>(a , S , s0 , F , f);
- //System.out.println(aut);
- System.out.println(aut.Iterate());
- }
- }
- class Automata<T > {
- int A;
- T s;
- Set<T> S = new HashSet<T>();
- Set<T> F = new HashSet<T>();
- Map<Pair<T , Character> , ArrayList<T>> f = new HashMap();
- Map<Pair<T , T> , ArrayList<Character>> inverse_f = new HashMap();
- Automata(int _A , Set<T> _S , T _s , Set<T> _F , Map<Pair<T , Character> , ArrayList<T>> _f){
- A = _A;
- s = _s;
- S = _S;
- F = _F;
- f = _f;
- for(Map.Entry<Pair<T , Character> , ArrayList<T>> i : f.entrySet()){
- Pair<T , ArrayList<T>> pr = new Pair<T , ArrayList<T>>(i.getKey().first() , i.getValue());
- for(T cur : pr.second()){
- Pair<T,T> cp = new Pair<T,T>(pr.first() , cur);
- if(!inverse_f.containsKey(cp)){
- inverse_f.put(cp , new ArrayList<Character>());
- }
- if(!inverse_f.get(cp).contains(i.getKey().second())){
- inverse_f.get(cp).add(i.getKey().second());
- }
- }
- }
- }
- public String toString(){
- String res = "";
- res += A;
- res += '\n';
- res += S.size() + "\n";
- res += S.toString() + "\n";
- res += s.toString() + "\n";
- res += F.size() + "\n";
- res += F.toString() + "\n";
- res += f.toString();
- return res;
- }
- public Automata<Pair<Integer , T>> Iterate(){
- int new_A = this.A;
- Set<Pair<Integer , T> > new_S = new HashSet();
- for(T i : this.S){
- new_S.add(new Pair<Integer , T>(1 , i));
- }
- Pair<Integer , T> new_s = new Pair(2 , this.s);
- new_S.add(new_s);
- Set<Pair<Integer , T> > new_F = new HashSet();
- for(T i : this.F){
- new_F.add(new Pair<Integer , T>(1 , i));
- }
- new_F.add(new_s);
- Map<Pair<Pair<Integer , T> , Character> , ArrayList<Pair<Integer , T>> > new_f = new HashMap();
- for(Pair<T , Character> key : this.f.keySet()){
- boolean ck = this.F.contains(key.first());
- if(this.F.contains(key.first())){
- if(this.f.containsKey(new Pair(this.s , key.second()))){
- ArrayList<T> to = this.f.get(new Pair(this.s , key.second()));
- Pair<Integer , T> new_key1 = new Pair<Integer , T>(1 , key.first());
- Pair<Pair<Integer , T> , Character> new_key = new Pair(new_key1 , key.second());
- if(!new_f.containsKey(new_key)){
- new_f.put(new_key , new ArrayList<Pair<Integer,T>>());
- }
- for(T v : to){
- new_f.get(new_key).add(new Pair<Integer , T>(1 , v));
- }
- }
- }
- ArrayList<T> to = this.f.get(key);
- Pair<Integer , T> new_key1 = new Pair<Integer , T>(1 , key.first());
- Pair<Pair<Integer , T> , Character> new_key = new Pair(new_key1 , key.second());
- for(T v : to){
- if(!new_f.containsKey(new_key)){
- new_f.put(new_key , new ArrayList<Pair<Integer,T>>());
- }
- new_f.get(new_key).add(new Pair<Integer , T>(1 , v));
- if(ck){
- }
- }
- }
- for(char c = 'a' ; c < 'a' + A ; ++c){
- Pair<T , Character> cur = new Pair(this.s , c);
- // System.out.println("cur: " + cur + " f: " + f);
- for(Pair<T , Character> key : f.keySet()) {
- if (key.first().equals(cur.first()) && key.second().equals(cur.second())) {
- Pair<Pair<Integer, T>, Character> pt = new Pair<Pair<Integer, T>, Character>(new_s, c);
- if (!f.containsKey(pt)) {
- new_f.put(pt, new ArrayList<Pair<Integer, T>>());
- }
- ArrayList<T> to = f.get(key);
- if(to == null)continue;
- for (T v : to) {
- Pair<Integer, T> p = new Pair(1, v);
- new_f.get(pt).add(p);
- }
- }
- }
- }
- Automata<Pair<Integer , T> > res = new Automata<Pair<Integer , T> >(new_A , new_S , new_s , new_F , new_f);
- return res;
- }
- public Automata<Pair<Integer , T>> Concat(Automata<T> b){
- int new_A = Math.max(this.A , b.A);
- Set<Pair<Integer , T> > new_S = new HashSet();
- for(T i : this.S){
- new_S.add(new Pair<Integer , T>(1 , i));
- }
- for(T i : b.S){
- new_S.add(new Pair<Integer , T>(2 , i));
- }
- Pair<Integer , T> new_s = new Pair(1 , this.s);
- Set<Pair<Integer , T> > new_F = new HashSet();
- for(T i : b.F){
- new_F.add(new Pair<Integer , T>(2 , i));
- }
- if(/*тут должна быть проверка на допустимость пустого слова*/b.F.contains(b.s)){
- for(T i : this.F){
- new_F.add(new Pair<Integer , T>(1 , i));
- }
- }
- Map<Pair<Pair<Integer , T> , Character> , ArrayList<Pair<Integer , T>> > new_f = new HashMap();
- for(Pair<T , Character> key : b.f.keySet()){
- ArrayList<T> to = b.f.get(key);
- Pair<Integer , T> new_key1 = new Pair<Integer , T>(2 , key.first());
- Pair<Pair<Integer , T> , Character> new_key = new Pair(new_key1 , key.second());
- for(T v : to){
- if(!new_f.containsKey(new_key)){
- new_f.put(new_key , new ArrayList<Pair<Integer,T>>());
- }
- new_f.get(new_key).add(new Pair<Integer , T>(2 , v));
- }
- }
- for(Pair<T , Character> key : this.f.keySet()){
- ArrayList<T> to = this.f.get(key);
- Pair<Integer , T> new_key1 = new Pair<Integer , T>(1 , key.first());
- Pair<Pair<Integer , T> , Character> new_key = new Pair(new_key1 , key.second());
- for(T v : to){
- if(!new_f.containsKey(new_key)){
- new_f.put(new_key , new ArrayList<Pair<Integer,T>>());
- }
- new_f.get(new_key).add(new Pair<Integer , T>(1 , v));
- }
- }
- for(char c = 'a' ; c < 'a' + A ; ++c){
- Pair<T , Character> cur = new Pair(b.s , c);
- // System.out.println("cur: " + cur + " f: " + f);
- for(Pair<T , Character> key : b.f.keySet()) {
- if (key.first().equals(cur.first()) && key.second().equals(cur.second())) {
- Pair<Pair<Integer, T>, Character> pt = new Pair<Pair<Integer, T>, Character>(new_s, c);
- if (!b.f.containsKey(pt)) {
- new_f.put(pt, new ArrayList<Pair<Integer, T>>());
- }
- ArrayList<T> to = b.f.get(key);
- if(to == null)continue;
- for (T v : to) {
- Pair<Integer, T> p = new Pair(1, v);
- new_f.get(pt).add(p);
- }
- }
- }
- }
- Automata<Pair<Integer , T> > res = new Automata<Pair<Integer , T> >(new_A , new_S , new_s , new_F , new_f);
- return res;
- }
- public Automata<Pair<Integer , T>> Add(Automata<T> b){
- int new_A = Math.max(this.A , b.A);
- Set<Pair<Integer , T> > new_S = new HashSet();
- for(T i : this.S){
- new_S.add(new Pair<Integer , T>(1 , i));
- }
- for(T i : b.S){
- new_S.add(new Pair<Integer , T>(2 , i));
- }
- Pair<Integer , T> new_s = new Pair<Integer , T>(3 , this.s);
- new_S.add(new_s);
- Set<Pair<Integer , T> > new_F = new HashSet();
- for(T i : this.F){
- new_F.add(new Pair<Integer , T>(1 , i));
- }
- for(T i : b.F){
- new_F.add(new Pair<Integer , T>(2 , i));
- }
- if(/*тут должна быть проверка на допустимость пустого слова*/ this.F.contains(this.s) || b.F.contains(b.s)){
- new_F.add(new_s);
- }
- Map<Pair<Pair<Integer , T> , Character> , ArrayList<Pair<Integer , T>> > new_f = new HashMap();
- for(Pair<T , Character> key : this.f.keySet()){
- ArrayList<T> to = this.f.get(key);
- Pair<Integer , T> new_key1 = new Pair<Integer , T>(1 , key.first());
- Pair<Pair<Integer , T> , Character> new_key = new Pair(new_key1 , key.second());
- for(T v : to){
- if(!new_f.containsKey(new_key)){
- new_f.put(new_key , new ArrayList<Pair<Integer,T>>());
- }
- new_f.get(new_key).add(new Pair<Integer , T>(1 , v));
- }
- }
- for(Pair<T , Character> key : b.f.keySet()){
- ArrayList<T> to = b.f.get(key);
- Pair<Integer , T> new_key1 = new Pair<Integer , T>(2 , key.first());
- Pair<Pair<Integer , T> , Character> new_key = new Pair(new_key1 , key.second());
- for(T v : to){
- if(!new_f.containsKey(new_key)){
- new_f.put(new_key , new ArrayList<Pair<Integer,T>>());
- }
- new_f.get(new_key).add(new Pair<Integer , T>(2 , v));
- }
- }
- for(char c = 'a' ; c < 'a' + new_A ; ++c){
- if(this.f.containsKey(new Pair<T , Character>(this.s , c))){
- if(!new_f.containsKey(new Pair(new_s , c))){
- new_f.put(new Pair(new_s , c) , new ArrayList<Pair<Integer , T>>());
- }
- ArrayList<T> to = this.f.get(new Pair<T , Character>(this.s , c));
- for(T v : to){
- new_f.get(new Pair(new_s , c)).add(new Pair<Integer , T>(1 , v));
- }
- }
- if(b.f.containsKey(new Pair<T , Character>(b.s , c))){
- if(!new_f.containsKey(new Pair(new_s , c))){
- new_f.put(new Pair(new_s , c) , new ArrayList<Pair<Integer , T>>());
- }
- ArrayList<T> to = b.f.get(new Pair<T , Character>(b.s , c));
- for(T v : to){
- new_f.get(new Pair(new_s , c)).add(new Pair<Integer , T>(2 , v));
- }
- }
- }
- Automata<Pair<Integer , T> > res = new Automata<Pair<Integer , T> >(new_A , new_S , new_s , new_F , new_f);
- return res;
- }
- public Automata<Pair<T , T> > Multiply (Automata<T> b){
- int new_A = Math.max(this.A, b.A);
- Set<Pair<T , T> > new_S = new HashSet<Pair<T , T> >();
- for(T i: this.S){
- for(T j: b.S){
- Pair<T , T> pr = new Pair<T, T>(i , j);
- new_S.add(pr);
- }
- }
- Set<Pair<T , T> > new_F = new HashSet<Pair<T , T> >();
- for(T i: this.F){
- for(T j: b.F){
- Pair<T , T> pr = new Pair<T , T>(i , j);
- new_F.add(pr);
- }
- }
- Pair<T , T> new_s = new Pair<T , T>(this.s , b.s);
- Map<Pair<Pair<T , T> , Character> , ArrayList<Pair<T , T>> > new_f = new HashMap();
- for(Pair<T , Character> i : this.f.keySet()){
- for(Pair<T , Character> j : b.f.keySet()){
- if(i.second() != j.second())continue;
- for(Pair<T , T> k : new_S){
- if(i.first() == k.first() && j.first() == k.second()){
- Pair<Pair<T , T> , Character> pr = new Pair<Pair<T , T> , Character>(k , (char)i.second());
- // Pair<T , T> put_pair = new Pair<T, T>(this.f.get(i) , b.f.get(j));
- ArrayList<T> tf = this.f.get(i);
- ArrayList<T> bf = b.f.get(i);
- for(T curt : tf){
- for(T curb : bf){
- Pair<T , T> put_pair = new Pair<T , T>(curt , curb);
- if(!new_f.containsKey(pr)){
- new_f.put(pr , new ArrayList<Pair<T , T>>());
- }
- new_f.get(pr).add(put_pair);
- }
- }
- }
- }
- }
- }
- Automata<Pair<T , T> > res = new Automata<Pair<T , T> >(new_A , new_S , new_s , new_F , new_f);
- return res;
- }
- }
- class Pair<T1 , T2 >{
- T1 x;
- T2 y;
- Pair(T1 _x , T2 _y){
- x = _x;
- y = _y;
- }
- T1 first(){
- return x;
- }
- T2 second(){
- return y;
- }
- public String toString(){
- return "{" + x.toString() + " ; " + y.toString() + "}";
- }
- public boolean equals(Object other){
- if (other instanceof Pair) {
- Pair otherPair = (Pair) other;
- return
- (( this.x == otherPair.x ||
- ( this.x != null && otherPair.x != null &&
- this.x.equals(otherPair.x))) &&
- ( this.y == otherPair.y ||
- ( this.y != null && otherPair.y != null &&
- this.y.equals(otherPair.y))) );
- }
- return false;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement