• SDOI2008 Sandy的卡片


    传送门

    这题数据范围贼小……听说可以用各种乱七八糟的暴力随便过去。

    其实这题就是找最长公共子串。但是我一直不知道怎么处理加数的情况……今天豁然开朗,直接对每个串做一次差分就好了。

    之后就是我们正常的匹配,每次用子树内的值更新节点的值,最后的时候答案取所有节点最小匹配值的最大值+1.

    #include<bits/stdc++.h>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    
    using namespace std;
    typedef long long ll;
    const int M = 100005;
    const int N = 2000005;
    const ll INF = 5e18;
    
    int read()
    {
       int ans = 0,op = 1;char ch = getchar();
       while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
       while(ch >='0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar();
       return ans * op;
    }
    
    int n,ans,maxn[M],minn[M],a[M],c[M],b[M];
    
    struct Suffix
    {
        map <int,int> ch[M];
        int last,cnt,fa[M],l[M];
        void extend(int c)
        {
            int p = last,np = ++cnt;
            l[np] = l[p] + 1,last = cnt;
            while(p && !ch[p].count(c)) ch[p][c] = np,p = fa[p];
            if(!p) {fa[np] = 1;return;}
            int q = ch[p][c];
            if(l[q] == l[p] + 1) fa[np] = q;
            else
            {
                int nq = ++cnt;
                l[nq] = l[p] + 1,ch[nq] = ch[q];
                fa[nq] = fa[q],fa[np] = fa[q] = nq;
                while(ch[p][c] == q) ch[p][c] = nq,p = fa[p];
            }
        }
        void cal()
        {
            rep(i,1,cnt) c[l[i]]++;
            rep(i,1,cnt) c[i] += c[i-1];
            rep(i,1,cnt) a[c[l[i]]--] = i;
        }
        void match(int *b,int k)
        {
            int u = 1,len = 0;
            rep(i,2,k) 
            {
                int f = b[i] - b[i-1];
                while(u != 1 && !ch[u][f]) u = fa[u],len = l[u];
                if(ch[u][f]) len++,u = ch[u][f],maxn[u] = max(maxn[u],len);
            }
            per(i,cnt,1)
            {
                int p = a[i];
                maxn[fa[p]] = max(maxn[fa[p]],min(maxn[p],l[fa[p]]));
                minn[p] = min(minn[p],maxn[p]),maxn[p] = 0;
            }
        }
    }SAM;
    
    int main()
    {
        n = read(),SAM.cnt = SAM.last = 1;
        memset(minn,0x3f,sizeof(minn));
        int k = read();
        rep(i,1,k) {b[i] = read(); if(i >= 2) SAM.extend(b[i] - b[i-1]);}
        SAM.cal();
        rep(i,2,n)
        {
            int k = read();
            rep(i,1,k) b[i] = read();
            SAM.match(b,k);
        }
        rep(i,1,SAM.cnt) ans = max(ans,minn[i]+1);
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    PHP7还没学明白,PHP8就要来了, 能有多快?
    Linux ab 压力测试
    大公司为什么都有API网关?没你想的那么简单!
    mac安装的vagrant访问laraval欢迎页面,执行时间15秒,安装nfs挂载点(亲测可行)
    PHP操作Elasticsearch
    PHP OpenSSL扩展 对称加密
    为什么 select count(*) from t,在 InnoDB 引擎中比 MyISAM 慢?
    Redis哨兵机制
    未来三五年,社会上什么工作会更吃香呢?这几方面
    自己的 Doxyfile 模板
  • 原文地址:https://www.cnblogs.com/captain1/p/10275078.html
Copyright © 2020-2023  润新知