예제 #1
0
        public void Solve()
        {
            var n  = sc.Integer();
            var s  = sc.Scan();
            var SA = new SuffixArray(s);

            SA.Init();
            SA.BuildLCP();
            var a = Enumerate(s.Length, x => x);

            Array.Sort(a, (l, r) =>
            {
                //Debug.WriteLine("{0} {1}", l, r);
                if (l == r)
                {
                    return(0);
                }
                var lcp = SA.GetLCP(l, r);
                if (Math.Max(l, r) + lcp < s.Length)
                {
                    return(SA.Rank(l).CompareTo(SA.Rank(r)));
                }
                else
                {
                    var lcp2 = SA.GetLCP(Math.Min(l, r), Math.Min(l, r) + lcp);
                    if (lcp2 < Math.Max(r, l) - Math.Min(r, l))
                    {
                        if (l < r)
                        {
                            return(SA.Rank(l + lcp).CompareTo(SA.Rank(l)));
                        }
                        else
                        {
                            return(SA.Rank(r).CompareTo(SA.Rank(r + lcp)));
                        }
                    }
                    else
                    {
                        return(0);
                    }
                }
            });
            foreach (var x in a)
            {
                IO.Printer.Out.WriteLine(x + 1);
            }
        }
예제 #2
0
파일: 1143537.cs 프로젝트: qifanyyy/CLCDSA
        public void Solve()
        {
            var n    = sc.Integer();
            var k    = sc.Integer();
            var back = new int[k + 1];

            for (int i = 0; i < k; i++)
            {
                back[i] = -1;
            }
            back[k] = n;
            var s = sc.Scan(n);

            for (int i = n - 1; i >= 0; i--)
            {
                for (int j = 0; j <= k; j++)
                {
                    if (back[j] != -1 && j - s[i].Length >= 0)
                    {
                        back[j - s[i].Length] = Math.Max(back[j - s[i].Length], i);
                    }
                }
            }
            SuffixArray sa;
            {
                var sb = new StringBuilder();
                for (int i = 0; i < n; i++)
                {
                    sb.Append(s[i]);
                    sb.Append((char)('z' + 1));
                }
                sa = new SuffixArray(sb.ToString());
                sa.Init();
                sa.BuildLCP();
            }
            var dp = new bool[k + 1];

            dp[0] = true;
            var best = Enumerate(k, x => '|');

            var sum = 0;

            for (int i = 0; i < n; i++)
            {
                var len   = s[i].Length;
                var zs    = StringEx.ZAlgorithm(string.Concat(s[i], "$", new string(best)));
                var npos  = -1;
                var npos2 = -1;
                var next  = Enumerate(k + 1, x => - 100);
                for (int j = k - 1; j >= 0; j--)
                {
                    if (j + len > k)
                    {
                        continue;
                    }
                    if (!dp[j])
                    {
                        continue;
                    }
                    if (back[j + len] <= i)
                    {
                        continue;
                    }
                    var lcp = zs[len + 1 + j];
                    if (j + lcp != k && lcp != s[i].Length && best[j + lcp] > s[i][lcp])
                    {
                        npos          = j;
                        npos2         = j + lcp;
                        next[j + len] = npos;
                        continue;
                    }
                    if (j + lcp != k && lcp != s[i].Length && best[j + lcp] < s[i][lcp])
                    {
                        continue;
                    }
                    if (j + lcp == k || lcp == s[i].Length)
                    {
                        continue;
                    }
                    if (npos != -1)
                    {
                        if (j + len <= npos)
                        {
                            npos          = j;
                            npos2         = j + 1;
                            next[j + len] = npos;
                        }
                        else
                        {
                            var lcp2 = sa.GetLCP(sum, sum + npos - j);
                            if (npos - j + lcp2 == len)
                            {
                                next[j + len] = npos;
                            }
                            else if (s[i][lcp2] > s[i][npos - j + lcp2])
                            {
                                npos          = j;
                                npos2         = j + lcp2;
                                next[j + len] = npos;
                            }
                        }
                    }
                }
                if (npos != -1)
                {
                    for (int j = 0; j < len; j++)
                    {
                        best[npos + j] = s[i][j];
                    }
                    for (int j = npos + len; j < k; j++)
                    {
                        best[j] = '|';
                    }
                    for (int j = npos2 + 1; j <= k; j++)
                    {
                        dp[j] = false;
                    }
                    dp[npos]       = true;
                    dp[npos + len] = true;
                    for (int j = 0; j <= k; j++)
                    {
                        if (next[j] == npos)
                        {
                            dp[j] |= true;
                        }
                    }
                }
                sum += len + 1;
            }
            IO.Printer.Out.WriteLine(best);
        }