zoukankan      html  css  js  c++  java
  • hihocoder-1407 后缀数组二·重复旋律2 不重合 最少重复K次

     后缀数组不能直接通过Height得出不重合的公共串。我们可以二分k值,这样连续的Height只要都大于等于k,那他们互相间的k值都大于等于k。每个这样的连续区间查找SA的最大最小值,做差判断是否重合(考虑common prefix=k)。

    #include <iostream>
    #include <cstring>
    #include <string>
    #include <queue>
    #include <vector>
    #include <map>
    #include <set>
    #include <stack>
    #include <cmath>
    #include <cstdio>
    #include <algorithm>
    #include <iomanip>
    #include <stdlib.h> 
    #include <time.h>  
    #define LL long long
    using namespace std;
    const LL mod = 100001;
    const LL N = 100010;
    class SF
    {
        //N:数组大小
    public:
        int x[N], y[N], c[N];
        int Height[N],str[N], SA[N], Rank[N];//Height数组从2开始
        int slen;
        int m=1050;//字符集处理大小(传入如果不是数字,需要做位移转换)
        bool cmp(int* r, int a, int b, int l) {
            return r[a] == r[b] && r[a + l] == r[b + l];
        }
    
        void Suffix(int n) {
            ++n;
            int i, j, p;
            for (i = 0; i < m; ++i) c[i] = 0;
            for (i = 0; i < n; ++i) c[x[i] = str[i]]++;
            for (i = 1; i < m; ++i) c[i] += c[i - 1];
            for (i = n - 1; i >= 0; --i) SA[--c[x[i]]] = i;
            for (j = 1; j <= n; j <<= 1) {
                p = 0;
                for (i = n - j; i < n; ++i) y[p++] = i;
                for (i = 0; i < n; ++i) if (SA[i] >= j) y[p++] = SA[i] - j;
                for (i = 0; i < m; ++i) c[i] = 0;
                for (i = 0; i < n; ++i) c[x[y[i]]]++;
    
                for (i = 1; i < m; ++i) c[i] += c[i - 1];
                for (i = n - 1; i >= 0; --i) SA[--c[x[y[i]]]] = y[i];
    
                swap(x, y);
                p = 1; x[SA[0]] = 0;
                for (i = 1; i < n; ++i) {
                    x[SA[i]] = cmp(y, SA[i - 1], SA[i], j) ? p - 1 : p++;
                }
                if (p >= n)break;
                m = p;
            }
    
            int k = 0;
            n--;
            for (i = 0; i <= n; ++i) Rank[SA[i]] = i;
            for (i = 0; i < n; ++i) {
                if (k)--k;
                j = SA[Rank[i] - 1];
                while (str[i + k] == str[j + k])++k;
                Height[Rank[i]] = k;
                //cout << k << endl;
            }
        }
        void init(vector<int> &vv)
        {
            slen = vv.size();
            for (int i = 0; i < slen; i++)
                str[i] = vv[i]+2;//如果是字符,映射成从1开始的序列
            str[slen] = 1;//0作为结束符,防止越界
            Suffix(slen);
        }
        struct nod
        {
            int mx, mi;
        };
        int ans;
        bool ok(int k)
        {
            int temp = 0;
            int mx = 0, mi = 10000;
            bool f = false;
            for (int i = 2; i <= slen; i++)
            {
                if (Height[i] >= k)
                {
                    mx = max(mx, max(SA[i - 1], SA[i]));
                    mi = min(mi, min(SA[i - 1], SA[i]));
                }
                else
                {
                    mx = 0;
                        mi = 10000;
                }
                if (mx - mi >= k)f = true;
            }
            return f;
        }
        int go(int l, int r)
        {
            for (; r >= l; r--)
                if (ok(r))return r;
            return 0;
        }
        int bins(int l, int r)
        {
            while (l <= r)
            {
                if(r-l<=3)
                    return go(l, r);
                int mid = (l + r) / 2;
                if (ok(mid))
                    l = mid;
                else r = mid - 1;
            }
        }
        LL solve()
        {
            ans=bins(0, slen);
            return ans;
        }
    }sf;
    LL dp[35][2];
    LL n;
    int main() {
        cin.sync_with_stdio(false);
        while (cin >> n)
        {
            vector<int> v;
            for (int i = 0; i < n; i++)
            {
                int num;
                cin >> num;
                v.push_back(num);
            }
            sf.init(v);
            cout << sf.solve() << endl;
        }
        return 0;
    }
  • 相关阅读:
    美国商务签证面试经历
    正则表达式匹配字符串中的数值部分并将其返回
    在WPF中使用水晶报表for vs2010的方法
    Wpf中用代码执行控件的单击事件
    WPF项目中使用水晶报表for vs2010时的一个找不到程序集的问题
    WinForm实现全屏方法
    wpf中将数据导出为Excel
    WinForm实现窗体上控件的自由拖动
    在WPF中使用WinForm控件方法
    多样、互动的WinForm UI设计与开发思路(Flash、Html等)
  • 原文地址:https://www.cnblogs.com/LukeStepByStep/p/7553392.html
Copyright © 2011-2022 走看看