본문 바로가기
Algorithm/BOJ

백준 9250번 : 문자열 집합 판별 - 아호코라식 Java

by catchJava 2023. 1. 6.

https://www.acmicpc.net/problem/9250

 

9250번: 문자열 집합 판별

집합 S는 크기가 N이고, 원소가 문자열인 집합이다. Q개의 문자열이 주어졌을 때, 각 문자열의 부분 문자열이 집합 S에 있는지 판별하는 프로그램을 작성하시오. 문자열의 여러 부분 문자열 중 하

www.acmicpc.net

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//package org.example;
 
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;
 
public class Main {
    final int MX = 26;
 
    class Trie {
        Trie child[];
        Trie fail;
        boolean output;
 
        public Trie() {
            child = new Trie[MX];
            Arrays.fill(child, null);
        }
 
        void insert(String str) {
            Trie tmp = this;
            for (int i = 0; i < str.length(); i++) {
                int cur = str.charAt(i) - 'a';
 
                if (tmp.child[cur] == null) {
                    tmp.child[cur] = new Trie();
                }
                tmp = tmp.child[cur];
            }
            tmp.output = true;
        }
 
        boolean check(String str) {
            Trie tmp = this;
 
            for (int i = 0; i < str.length(); i++) {
                int next = str.charAt(i) - 'a';
 
                while(tmp!= this && tmp.child[next] == null){
                    tmp = tmp.fail;
                }
                if(tmp.child[next]!=null){
                    tmp = tmp.child[next];
                }
                if(tmp.output){
                    return true;
                }
            }
 
            return false;
        }
 
        void computeFailFunc(){
            Queue<Trie> q = new LinkedList<>();
            Trie root = this;
            root.fail = this;
            q.add(root);
 
            while(!q.isEmpty()){
                Trie here = q.poll();
 
                for(int edge = 0; edge<MX; edge++){
                    Trie child = here.child[edge];
                    if(child == nullcontinue;
 
                    if(here == root) child.fail = root;
                    else{
                        Trie t = here.fail;
 
                        while(t!=root && t.child[edge] == null){
                            t = t.fail;
                        }
 
                        if(t.child[edge] != null) t = t.child[edge];
                        child.fail = t;
                    }
 
                    if(child.fail.output) child.output = true;
                    q.add(child);
                }
            }
        }
    }
 
    public void solution() throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();
 
        Trie root = new Trie();
 
        int N = Integer.parseInt(br.readLine());
        for (int i = 0; i < N; i++) {
            String str = br.readLine();
            root.insert(str);
        }
 
        root.computeFailFunc();
 
        int M = Integer.parseInt(br.readLine());
        for (int i = 0; i < M; i++) {
            String str = br.readLine();
            if (root.check(str)) sb.append("YES\n");
            else sb.append("NO\n");
        }
        System.out.println(sb);
    }
 
    public static void main(String[] args) throws Exception {
        new Main().solution();
    }
}
 
cs