BZOJ 4698: Sdoi2008 Sandy的卡片 [后缀自动机]

4698: Sdoi2008 Sandy的卡片

题意:差分后就是多个串LCS


SAM+map大法好

模板打错 智力-2

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
typedef long long ll;
const int N=2005;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

namespace sam{
    struct meow{map<int, int> ch; int par, val;} t[N];
    int sz=1, last=1, root=1;
void extend(int c) {
    int p=last, np=++sz; t[np].val=t[p].val+1;
    for(; p && !t[p].ch[c]; p=t[p].par) t[p].ch[c]=np;
    if(!p) t[np].par = root;
    else {
        int q = t[p].ch[c];
        if(t[q].val == t[p].val+1) t[np].par = q;
        else {
            int nq = ++sz; t[nq]=t[q]; t[nq].val=t[p].val+1;
            t[q].par = t[np].par = nq;
            for(; p && t[p].ch[c]==q; p=t[p].par) t[p].ch[c] = nq;
        }
    }
    last=np;
}
    int c[N], a[N], ans[N];
    void RadixSort() {
        for(int i=0; i<=sz; i++) c[i]=0;
        for(int i=1; i<=sz; i++) c[t[i].val]++;
        for(int i=1; i<=sz; i++) c[i] += c[i-1];
        for(int i=sz; i>=1; i--) a[ c[t[i].val]-- ]=i;
        for(int i=1; i<=sz; i++) ans[i] = t[i].val;
    }

    int f[N]; // max lenth
    void solve(int *s, int n) { //puts("\n solve");
        int u=root, now=0;
        for(int i=1; i<=n; i++) {
            int c = s[i]; //printf("i %d  %d\n",i,c);
            if(t[u].ch.count(c)) u=t[u].ch[c], f[u] = max(f[u], ++now);
            else {
                while(u && !t[u].ch.count(c)) u=t[u].par;
                if(!u) u=root, now=0;
                else now=t[u].val, u=t[u].ch[c], f[u] = max(f[u], ++now);
            }
        }
        for(int i=sz; i>=1; i--) {
            int u=a[i]; ans[u] = min(ans[u], f[u]); //printf("f %d %d\n",u,f[u]);
            if(f[u] && t[u].par) f[t[u].par] = t[t[u].par].val;
            f[u]=0;
        }
    }
}
int n, len, s[N], last, x;
int main() {
    freopen("in","r",stdin);
    n=read();
    len=read(); last=read();
    for(int i=1; i<len; i++) x=read(), s[i]=x-last, last=x;
    len--;
    for(int i=1; i<=len; i++) sam::extend(s[i]);
    sam::RadixSort();
    for(int i=2; i<=n; i++) {
        len=read(); last=read();
        for(int i=1; i<len; i++) x=read(), s[i]=x-last, last=x;
        len--;
        sam::solve(s, len);
    }
    int ans=0;
    for(int i=2; i<=sam::sz; i++) ans = max(ans, sam::ans[i]);
    printf("%d", ans+1);
}

转载于:https://www.cnblogs.com/candy99/p/6675536.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值