private string toStringEdgeTable(int wordNum,
                                             bool doAddIds  = true,
                                             bool doAddTree = true)
            {
                StringBuilder sb           = new StringBuilder();
                string        edgesBanner  = toStringEdgeBanner(wordDict.Values.Select(w => w.Length).Max());
                string        addIdsSpacer = "  Id  ";

                int[] wordNums = (wordNum == GSuffixTree.NoWordNum)
                    ? wordDict.Keys.ToArray()
                    : new int[] { wordNum };
                if (doAddIds)
                {
                    sb.Append(addIdsSpacer);
                }
                sb.AppendLine(edgesBanner);
                foreach (DepthTaggedGstEdge dtEdge in DepthTaggedEdges())
                {
                    GstEdge edge      = dtEdge.Edge;
                    string  formatStr = "  {0,-11:d}{1,-11:d}{2,-11:s}{3,-11:d}{4,-11:d}{5,-9:d}{6,-"
                                        + Math.Max(7, wordDict.Values.Select(w => 1 + w.Length).Max()).ToString()
                                        + ":s}";
                    for (int i = 0; i < wordNums.Length; i++)
                    {
                        if (!edge.HasWordNum(wordNums[i]))
                        {
                            continue;
                        }
                        if (doAddIds)
                        {
                            sb.Append(String.Format("  {0,-4:d}", edge.Id));
                        }
                        sb.Append(String.Format(formatStr,
                                                edge.ParentNode.Id, edge.ChildNode.Id,
                                                (edge.ChildNode.SuffixNode == null ? "null" : edge.ChildNode.SuffixNode.Id.ToString()),
                                                wordNums[i],
                                                edge.GetBeginIndex(wordNums[i]), edge.GetEndIndex(wordNums[i]),
                                                (new String(' ', edge.GetBeginIndex(wordNums[i]))) +
                                                GetRangeString(wordNums[i], edge.GetBeginIndex(wordNums[i]), edge.GetEndIndex(wordNums[i]))
                                                ));
                        if (doAddTree)
                        {
                            string depthStr = new String(' ', 2 * dtEdge.Depth - 1) + "*";
                            sb.AppendLine(depthStr);
                        }
                    }
                }
                return(sb.ToString());
            }
 /// <summary>
 ///     Rule #1 (Ukkonen's first group of t_i-transitions): Try to find matching edge for the parent node.
 /// </summary>
 /// <param name="parentNode">This is a member of active.  It is kept separate for clarity.</param>
 private ExtensionResult extendSuffixByRuleOne(
     ref GstSuffix active, ref GstNode parentNode, int endIndex, int wordNum)
 {
     if (active.IsExplicit)
     {
         GstEdge edge = active.OriginNode.GetChildEdge(GetWordChar(wordNum, endIndex));
         if (edge != null && edge.IsSet())
         {
             return(ExtensionResult.Done);
         }
     }
     else    // active suffix is implicit
     {
         GstEdge edge = active.OriginNode.GetChildEdge(GetWordChar(wordNum, active.BeginIndex));
         int     span = active.EndIndex - active.BeginIndex;
         if (edge != null)
         {
             int extantWordNum = edge.GetExtantWordNum();
             if (GetWordChar(extantWordNum, edge.GetBeginIndex(extantWordNum) + span + 1)
                 == GetWordChar(wordNum, endIndex))
             {
                 return(ExtensionResult.Done);
             }
             GstUtil.WriteLine(GstVerbosityLevel.Verbose, String.Format(
                                   "  Rule #1: About to split edge E{0:d} (\"{1:s}\") at suffix {2:s}",
                                   edge.Id, edge.GetText(), active.ToString()));
             parentNode = edge.Split(active);
         }
     }
     return(ExtensionResult.NotDone);
 }