Hiho 123 后缀数组四·重复旋律4

来源:互联网 发布:两个有序数组的中位数 编辑:程序博客网 时间:2024/05/22 06:53
首先枚举(k,l)中的这个l,再枚举起始位置i,计算Suffix(i)和Suffix(i+l)的LCP,记作lcp(l, i),那么k(l, i)就等于lcp(l,i)/l + 1。对于所有的循环节长度l和起始位置i,最大的k(l, i)就是答案。

using System;namespace Hiho{    class _123    {        static readonly int MAXN = 1000050;        static char[] ch = new char[MAXN], All = new char[MAXN];        static int[] SA = new int[MAXN], RANK = new int[MAXN], Height = new int[MAXN], tax = new int[MAXN], tp = new int[MAXN], original = new int[MAXN];        static int n, m;        static void RSort()        {            for (int i = 0; i <= m; i++) tax[i] = 0;            for (int i = 1; i <= n; i++) tax[RANK[tp[i]]]++;            for (int i = 1; i <= m; i++) tax[i] += tax[i - 1];            for (int i = n; i >= 1; i--) SA[tax[RANK[tp[i]]]--] = tp[i];        }        static bool cmp(int[] f, int x, int y, int w) { return f[x] == f[y] && f[x + w] == f[y + w]; }        static void Suffix()        {            //SA            for (int i = 1; i <= n; i++)            {                RANK[i] = original[i];                tp[i] = i;            }            m = 2000; RSort();            for (int w = 1, p = 1, i; p < n; w += w, m = p)            {                for (p = 0, i = n - w + 1; i <= n; i++) tp[++p] = i;                for (i = 1; i <= n; i++) if (SA[i] > w) tp[++p] = SA[i] - w;                RSort();                int[] temp = RANK;                RANK = tp;                tp = temp;                RANK[SA[1]] = p = 1;                for (i = 2; i <= n; i++) RANK[SA[i]] = cmp(tp, SA[i], SA[i - 1], w) ? p : ++p;            }            int j, k = 0;            for (int i = 1; i <= n; Height[RANK[i++]] = k)                for (k = k != 0 ? k - 1 : k, j = SA[RANK[i] - 1]; original[i + k] == original[j + k]; ++k) ;        }        static int LCP(int j, int k)        {            if (RANK[j] > RANK[k])            {                int temp = j;                j = k;                k = temp;            }            return (int)ask_min(RANK[j] + 1, RANK[k], 1);        }        //线段树        class Tree        {            public long l, r, add;            public long min;        }        static Tree[] tree = null;        //标记下放们 p == now        static long L(long x)        {            return x << 1;        }        static long R(long x)        {            return x << 1 | 1;        }        static void update(long p)        {            tree[p].min = Math.Min(tree[L(p)].min, tree[R(p)].min);        }        static void spread(long p)        {            if (tree[p].add == 0) return;            tree[L(p)].min += tree[p].add;            tree[R(p)].min += tree[p].add;            tree[L(p)].add += tree[p].add;            tree[R(p)].add += tree[p].add;            tree[p].add = 0;//!!!!!!!            update(p);            return;        }        static void build(long l, long r, long p)        {            if (tree[p] == null) tree[p] = new Tree();            tree[p].l = l;            tree[p].r = r;            if (l == r)            {                tree[p].min = Height[l];                return;            }            long mid = (tree[p].l + tree[p].r) >> 1;            build(l, mid, L(p));            build(mid + 1, r, R(p));            update(p);            return;        }        static long ask_min(long l, long r, long p)        {            if (l <= tree[p].l && tree[p].r <= r)            {                return tree[p].min;            }            spread(p);            long ans = int.MaxValue, mid = (tree[p].l + tree[p].r) >> 1;            if (l <= mid) ans = Math.Min(ans, ask_min(l, r, L(p)));            if (mid < r) ans = Math.Min(ans, ask_min(l, r, R(p)));            update(p);            return ans;        }        static void Main(string[] args)        {            string str = Console.ReadLine();            n = str.Length;            for (int i = 0; i < n; i++) original[i + 1] = str[i];            Suffix();            //segtree            tree = new Tree[4 * (n + 1)];            build(1, n, 1);            //            int ans = 0;            for (int L = 1; L <= n; L++)            {                for (int i = 1; i + L <= n; i += L)                {                    int R = LCP(i, i + L);                    ans = Math.Max(ans, R / L + 1);                    if (i >= L - R % L)                    {                        ans = Math.Max(LCP(i - L + R % L, i + R % L) / L + 1, ans);                    }                }            }            Console.WriteLine(ans);        }    }}



0 0
原创粉丝点击