OCR 문제 질문드립니다.

  • sven
    sven

    OCR

    #pragma GCC diagnostic ignored "-Wwrite-strings"
    //#pragma GCC diagnostic ignored "-Wc++11-extensions"
    
    #include <vector>
    #include <map>
    #include <set>
    #include <stack>
    #include <algorithm>
    #include <sstream>
    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <string>
    #include <cctype>
    #include <cstring>
    #include <queue>
    #include <cassert>
    #include <ctime>
    #include <cassert>
    #include <climits>
    #include "stdarg.h"
    #include <bitset> //http://stackoverflow.com/questions/4048749/bitwise-operations-on-vectorbool //http://www.drdobbs.com/the-standard-librarian-bitsets-and-bit-v/184401382
    
    using namespace std;
    
    typedef long long LL;
    typedef long double LD;
    typedef vector<int> VI;
    typedef vector<LL> VLL;
    typedef pair<int,int> PII;
    typedef vector<PII> VPII;
    typedef vector <VI> VVI;
    typedef vector <vector <double> > VVD;
    typedef vector <double> VD;
    typedef vector <string> VS;
    
    #define MP make_pair
    #define ST first
    #define ND second
    #define PB push_back
    #define FOR(i,a,b) for( int i=(a); i<=(b); ++i)
    #define FORD(i,a,b) for( int i=(a); i>=(b); --i)
    #define REP(i,n) for(int i=0; i<(n); ++i)
    #define ALL(X) (X).begin(),(X).end()
    #define SZ(X) (int)(X).size()
    #define FORE(it,X) for(__typeof((X).begin()) it=(X).begin(); it!=(X).end();++it)
    
    #define CE cout << endl;
    #define CL cout << "--------------------------------------" << endl;
    #define ASF assert(false);
    #define V vector
    
    template<template<typename, typename> class ContainerT, typename ValueT> //http://cboard.cprogramming.com/cplusplus-programming/145441-stl-container-template-argument.html
    ostream & operator << (ostream &out, const ContainerT<ValueT, std::allocator<ValueT> > &A) {
      FORE(i, A) out << *i << " "; return out;
    }
    
    template <class T, class U>
    ostream & operator << (ostream &out, const pair<T,U> &A) {
      out << A.ST << "-" << A.ND; return out;
    }
    
    
    #define VA_NARGS_IMPL(_1,_2,_3,_4,_5,_6,_7,_8,N,...) N
    #define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
    
    #define P_(a)                       #a << ": " << a
    #define P__(a)                      " | " << P_(a)
    #define P1(a)                       cout << P_(a) << endl;
    #define P2(a, b)                    cout << P_(a) << P__(b) << endl;
    #define P3(a, b, c)                 cout << P_(a) << P__(b) << P__(c) << endl;
    #define P4(a, b, c, d)              cout << P_(a) << P__(b) << P__(c) << P__(d) << endl;
    #define P5(a, b, c, d, e)           cout << P_(a) << P__(b) << P__(c) << P__(d) << P__(e) << endl;
    #define P6(a, b, c, d, e, f)        cout << P_(a) << P__(b) << P__(c) << P__(d) << P__(e) << P__(f) << endl;
    #define P7(a, b, c, d, e, f, g)     cout << P_(a) << P__(b) << P__(c) << P__(d) << P__(e) << P__(f) << P__(g) << endl;
    #define P8(a, b, c, d, e, f, g, h)  cout << P_(a) << P__(b) << P__(c) << P__(d) << P__(e) << P__(f) << P__(g) << P__(h) << endl;
    
    #define P_IMPL2(count, ...) P ## count (__VA_ARGS__)
    #define P_IMPL(count, ...) P_IMPL2(count, __VA_ARGS__) 
    #define P(...) P_IMPL(VA_NARGS(__VA_ARGS__), __VA_ARGS__)
    
    template<class T> void mini(T &a, const T &b) {if(b<a)a=b;}
    template<class T> void maxi(T &a, const T &b) {if(b>a)a=b;}
    
    int M, Q, N;
    VS corpus; //0+[1,M], 0 is imaginary word.
    VI R; //[0,N) -> [1,M], corpus index 
    VVD T; //0+[1,M] * [1,M], transition prob, 0 is imaginary word.
    VVD A; //[1,M] * [1,M], successing prob
    
    VVD cache; //cache
    VVI choice; //tracking
    #define NEG_INF -1e200
    
    template<class T>
    void init(V<V<T> > &A, int N, int M) {
      A.clear(); A.resize(N); REP(i, N) A[i].resize(M);
    }
    template<class T>
    void init(V<V<T> > &A, int N, int M, T val) {
      A.clear(); A.resize(N); REP(i, N) REP(j, M) A[i].PB(val);
    }
    
    double recognize(int segment, int previousMatch) {
      if(segment == N) return 0; //not log -> 1. identity of the operation
      assert(segment >= 0 and segment < N); //segment : [0,N)
      double &ret = cache[segment][previousMatch];
      if(ret != 1.0) return ret;
      ret = NEG_INF;
      int &choose = choice[segment][previousMatch];
      FOR(thisMatch, 1, M) {
        double cand = T[previousMatch][thisMatch]
                    + A[thisMatch][R[segment]]
                    + recognize(segment+1, thisMatch); //not log -> *
        if(ret < cand) {
          ret = cand;
          choose = thisMatch;
        }
      }
      assert(ret <= 0);
      assert(choose != 0); //means imaginary
      return ret;
    }
    
    string reconstruct(int segment, int previousMatch) {
      int choose = choice[segment][previousMatch];
      assert(choose >= 0 and choose <= M);
      string ret = corpus[choose];
      if(segment < N-1) ret = ret + " " + reconstruct(segment+1, choose);
      return ret;
    }
    
    double mylog(double a) {
      if(a == 0) return NEG_INF;
      else return log(a);
    }
    
    int main()
    {
      cin >> M >> Q;
      init(T, M+1, M+1);
      init(A, M+1, M+1);
      corpus.resize(M+1); REP(i, M) cin >> corpus[i+1];
      corpus[0] = "IMAGINARY";
      REP(i, M+1) REP(j, M) scanf("%lf", &T[i][j+1]);
      REP(i, M) REP(j, M) scanf("%lf", &A[i+1][j+1]);
    
      REP(i, M+1) REP(j, M) T[i][j+1] = mylog(T[i][j+1]);
      REP(i, M) REP(j, M) A[i+1][j+1] = mylog(A[i+1][j+1]);
    
      //solves for each query
      REP(i, Q) {
        R.clear();
        cin >> N;
        REP(j, N) {
          string temp;
          cin >> temp;
    //      FORE(k, corpus) if(*k == temp) R.PB(k-corpus.begin()); //there may exist corpus[0]
          FOR(k, 1, M) if(corpus[k] == temp) R.PB(k);
        }
        assert(R.size() == N);
        init(cache, M, M, 1.0);
        init(choice, M, M);
        recognize(0, 0);
        cout << reconstruct(0, 0) << endl;
      }
    
      return 0;
    }
    

    책의 코드대로 짜보려고 했습니다만, 잘 되지 않습니다.
    recognize 함수의 끝부분의 assert(choose != 0) 에서 걸려서, 런타임 에러가 뜹니다.
    문제가 되는 예제 데이터를 찾아보려고 했는데, 쉽지 않네요ㅜㅜ
    책의 트릭대로 가상의 단어 하나를 만들어서 생각했고, 각 변수의 범위를 선언부에 주석으로 적어두었습니다. choose 값이 0이라는 것은, choice[segment][previousMatch] 값 그대로라는 뜻이고, if(ret < cand) 루프 속으로 들어간 적이 없다는 의미입니다.
    (0은 가상의 단어이기 때문에, 루프를 1부터 M까지 돌고, choose 값은 [1, M] 이어야 합니다.)


    10년 전
2개의 댓글이 있습니다.
  • Being
    Being

    제가 보기에 의심되는 부분은,

    double cand = T[previousMatch][thisMatch]
        + A[thisMatch][R[segment]]
        + recognize(segment+1, thisMatch); //not log -> *
    

    이 부분인데요, 혹 A[thisMatch][R[segment]]가 항상 NEG_INF일 수 있지 않을까요? 각 행마다 합이 1이라고만 했지 어떤 열이 통째로 0일 수 있을 것 같습니다.


    10년 전 link
  • rlatkddn212
    rlatkddn212

    와..가상의 시작단어를 만든다는게 이런 뜻이였군요.
    덕분에 해결했습니다... 굉장한 트릭이네요.
    코드를 자세히 본건 아닌데 -1을 배열에 넣을수 없으니
    B[i] 부분을 행렬 T에 넣어 버려서 m+1 크기로 만드신 것 같아요.
    그 부분에서 잘못참조 되서 문제가 있지 않았을까요?..
    아무튼 저는 B[i] 부분을 행렬 T에 넣기는 하지만

    for (int i = 0; i < m; i++)
    {
    cin >> temp;
    T[m][i] = log(temp);
    }

    이런식으로 행렬 T의 제일 끝쪽에 넣어서 recognize 함수 안에 있는

    for (int thisMatch = 0; thisMatch < m; ++thisMatch){} 반복문을 피하게 했어요..

    호출할 때는 recognize(0, m); 사용했습니다.


    9년 전 link
  • 정회원 권한이 있어야 커멘트를 다실 수 있습니다. 정회원이 되시려면 온라인 저지에서 5문제 이상을 푸시고, 가입 후 7일 이상이 지나셔야 합니다. 현재 문제를 푸셨습니다.