using static IO; public class IO { public static IO Cin = new(); public static StreamReader reader = new(Console.OpenStandardInput()); public static StreamWriter writer = new(Console.OpenStandardOutput()); public static implicit operator string(IO _) => reader.ReadLine(); public static implicit operator char[](IO _) => reader.ReadLine().ToArray(); public static implicit operator int(IO _) => int.Parse(reader.ReadLine()); public static implicit operator double(IO _) => double.Parse(reader.ReadLine()); public static implicit operator string[](IO _) => reader.ReadLine().Split(); public static implicit operator int[](IO _) => Array.ConvertAll(reader.ReadLine().Split(), int.Parse); public void Deconstruct(out int a, out int b) { int[] r = Cin; (a, b) = (r[0], r[1]); } public void Deconstruct(out int a, out int b, out int c) { int[] r = Cin; (a, b, c) = (r[0], r[1], r[2]); } public static void Loop(int end, Action action, int start = 0, in int add = 1) { for (; start < end; start += add) action(start); } public static object? Cout { set { writer.Write(value); } } public static object? Coutln { set { writer.WriteLine(value); } } public static void Main() { Program.Coding(); writer.Flush(); } } class Program { public static void Coding() { checked { string text = Cin; int n = text.Length; int[] suffix = Enumerable.Range(0, n).ToArray(); int[] rank = text.Select(x => x - 'a').ToArray(); int[] next = new int[n]; for (int skip = 1; skip < n; skip <<= 1) { int Compare(int a, int b) { if (rank[a] != rank[b]) return rank[a].CompareTo(rank[b]); int ra = (a + skip < n) ? rank[a + skip] : -1; int rb = (b + skip < n) ? rank[b + skip] : -1; return ra.CompareTo(rb); } Array.Sort(suffix, Compare); next[suffix[0]] = 0; for (int i = 1; i < n; i++) { next[suffix[i]] = next[suffix[i - 1]] + (0 == Compare(suffix[i - 1], suffix[i]) ? 0 : 1); } Array.Copy(next, rank, n); if (rank[suffix[n - 1]] + 1 >= n) break; } int[] lcp = new int[n]; int h = 0; for (int i = 0; i < n; i++) { if (rank[i] + 1 >= n) { h = 0; continue; } for (int j = suffix[rank[i] + 1]; i + h < n && j + h < n && text[i + h] == text[j + h];) h++; lcp[rank[i]] = h; if (h > 0) h--; } Coutln = string.Join(' ', suffix.Select(i => i + 1)); Cout = "x " + string.Join(' ', lcp.SkipLast(1)); } } }