티스토리 뷰

DS\Algo

BOJ 5735 Emoticons :-)

MathTrauma 2022. 10. 8. 03:39

 

문제 링크 : https://www.acmicpc.net/problem/5735

 

5735번: Emoticons :-)

이모티콘은 채팅과 이메일에서 단어로 표현할 수 없는 감정을 나타내기 위해 종종 쓰인다. 이는 다양한 면에서 장점이 있지만, 많은 사람들은 이모티콘을 매우 짜증난다고 여기며, 없애고 싶어

www.acmicpc.net

 

아호-코라식(Aho-Corasick) 알고리즘 자체에 대해선 설명을 생략한다.

 

공백으로 대체해야할 문자의 개수를 최소화하는 방법은 무엇일까?

결론부터 말하면 텍스트를 검색해가면서 찾은 키워드(이모티콘)의 마지막 문자를 제거하면 된다.

 

텍스트 중에 등장하는 

               (-:-( 

을 보자. 가운데에 위치한 : 를 제거하면 (-: 과 :-( 의 두 개의 키워드를 제거할 수 있음을 알 수 있다.

만약 첫 문자나 두 번째 문자를 제거하면 첫 키워드는 제거할 수 있지만 두 번째 키워드는 제거되지 않는다.

 

이와 같은 상황은 일반적이다.

최소의 문자를 제거하는 최적해를 상상한다. 

제거한 문자의 위치가 앞에서부터 차례로 키워드가 발견되었을 때 키워드의 마지막 문자가 아닌 경우가 있다면,

그것들 중 최초의 것을 생각한다.

그 문자를 살려두고 키워드 마지막 문자를 지워서 손해보는 경우는 없음을 금새 알 수 있다.

 

#include<bits/stdc++.h>

using namespace std;

struct trie{
    trie *prv, *children[100];
    bool isEnd;
    trie() : isEnd{false}, prv{nullptr} { 
        for(int i=0;i<100;i++) children[i]=nullptr;
    }
    ~trie(){ 
        for(int i=0;i<100;i++ ) if(children[i]) 
            delete children[i]; 
    }
    
    void add(char *p){
        if(*p==0) { isEnd=true; return; }
        int id=*p-32;
        if(!children[id])
            children[id]=new trie();
        children[id]->add(p+1);
    }
} *rt;

int main(){
    while(true){
        int n,m; scanf("%d%d",&n,&m);
        if(n==0) break;
        
        rt=new trie();
        while(n--){
            char str[101];
            scanf("%s", str);
            rt->add(str);
        }

        queue<trie*> q;
        q.push(rt);
        while(!q.empty()){
            trie* cur = q.front();
            q.pop();
            for(int i=0; i<100; i++){
                trie* nxt = cur->children[i];
                if(!nxt) continue;
                if(cur==rt) nxt->prv=rt;
                else{
                    trie* t= cur->prv;
                    while( t!=rt && t->children[i]==nullptr)  
                        t=t->prv;
                    if(t->children[i]) 
                        t=t->children[i];
                    nxt->prv=t;
                }
                nxt->isEnd |= nxt->prv->isEnd;
                q.push(nxt);
            }
        }

        int ans = 0;
        getchar();
        while(m--){
            char str[102];
            fgets(str,101,stdin);
            str[strlen(str)-1]=0;
            trie* cur = rt;
            for(int i=0;i<strlen(str);i++){
                int id = str[i]-32;
                while(cur!=rt && cur->children[id]==nullptr) 
                    cur=cur->prv;
                if(cur->children[id]) 
                    cur=cur->children[id];
                if(cur->isEnd){
                    ans++;
                    cur=rt;  // 찾은 키워드의 마지막을 지우고 새로이 검색을 시작!
                }
            }
        }

        printf("%d\n",ans);
        delete rt;
    }
    return 0;
}

 

 

 

반응형

'DS\Algo' 카테고리의 다른 글

BOJ 14698 전생했더니 슬라임 연구자였던 건에 대하여 (Hard)  (0) 2022.10.10
BOJ 15486 퇴사 2  (0) 2022.10.09
BOJ 10256 Mutation( 돌연변이 )  (0) 2022.10.07
BOJ 13398 연속합 2  (0) 2022.10.07
BOJ 2056 작업  (0) 2022.10.06
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/06   »
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
글 보관함