code: def fill_alignment_matrix(
      fline2: str, fline3: str, gline2: str, gline3: str
  ) -> Tuple[np.ndarray, List[str], List[str]]:
      """Parse Giza++ direct and reverse alignment results and represent them as an alignment matrix
  
      Args:
          fline2: e.g. "_2 0 1 4_"
          fline3: e.g. "NULL ({ }) twenty ({ 1 }) fourteen ({ 2 3 4 })"
          gline2: e.g. "twenty fourteen"
          gline3: e.g. "NULL ({ }) _2 ({ 1 }) 0 ({ }) 1 ({ }) 4_ ({ 2 })"
  
      Returns:
          matrix: a numpy array of shape (src_len, dst_len) filled with [0, 1, 2, 3], where 3 means a reliable alignment
           the corresponding words were aligned to one another in direct and reverse alignment runs, 1 and 2 mean that the
           words were aligned only in one direction, 0 - no alignment.
          srctokens: e.g. ["twenty", "fourteen"]
          dsttokens: e.g. ["_2", "0", "1", "4_"]
  
      For example, the alignment matrix for the above example may look like:
      [[3, 0, 0, 0]
       [0, 2, 2, 3]]
      """
      if (
          fline2 is None
          or gline2 is None
          or fline3 is None
          or gline3 is None
      ):
          raise ValueError(f"empty params")
      srctokens = gline2.split()
      dsttokens = fline2.split()
      pattern = r"([^ ]+) \(\{ ([^\(\{\}\)]*) \}\)"
      src2dst = re.findall(pattern, fline3.replace("({ })", "({  })"))
      dst2src = re.findall(pattern, gline3.replace("({ })", "({  })"))
      if len(src2dst) != len(srctokens) + 1:
          raise ValueError(
              "length mismatch: len(src2dst)="
              + str(len(src2dst))
              + "; len(srctokens)"
              + str(len(srctokens))
              + "\n"
              + gline2
              + "\n"
              + fline3
          )
      if len(dst2src) != len(dsttokens) + 1:
          raise ValueError(
              "length mismatch: len(dst2src)="
              + str(len(dst2src))
              + "; len(dsttokens)"
              + str(len(dsttokens))
              + "\n"
              + fline2
              + "\n"
              + gline3
          )
      matrix = np.zeros((len(srctokens), len(dsttokens)))
      for i in range(1, len(src2dst)):
          token, to_str = src2dst[i]
          if to_str == "":
              continue
          to = list(map(int, to_str.split()))
          for t in to:
              matrix[i - 1][t - 1] = 2
  
      for i in range(1, len(dst2src)):
          token, to_str = dst2src[i]
          if to_str == "":
              continue
          to = list(map(int, to_str.split()))
          for t in to:
              matrix[t - 1][i - 1] += 1
  
      return matrix, srctokens, dsttokens
  
file_path: NeMo/nemo/collections/nlp/data/text_normalization_as_tagging/utils.py
imports: import re
  from itertools import groupby
  from typing import Dict, List, Tuple
  import numpy
label_desc: Use image node_id 8 for calling a global function with example usage: fill_alignment_matrix(fline2, fline3, gline2, gline3) and returns: matrix,  srctokens,  dsttokens