poj 1743 不可重叠最长重复子串


先考虑求一个出现次数>=2的最长子串

出现次数>=2那就只管|right(x)|>=2的点

然后对这些点的代表的子串长度取max即可

加上了不相交的限制,类似后缀数组的做法

我们就记录right集合的最大/最小值,他们的差值就是能不相交的最长长度

拿它和该点的maxs取min即可,然后对所有点的答案取max即可


SampleInput
30
25 27 30 34 39 45 52 60 69 79 69 60 52 45 39 34 30 26 22 18
82 78 74 70 66 67 64 60 65 80
0
SampleOutput
5


//china no.1
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <vector>
#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <cstring>
#include <queue>
#include <list>
#include <stdio.h>
#include <set>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <cctype>
#include <sstream>
#include <functional>
#include <stdlib.h>
#include <time.h>
#include <bitset>
using namespace std;

#define pi acos(-1)
#define s_1(x) scanf("%d",&x)
#define s_2(x,y) scanf("%d%d",&x,&y)
#define s_3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define PI acos(-1)
#define endl '\n'
#define srand() srand(time(0));
#define me(x,y) memset(x,y,sizeof(x));
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define close() ios::sync_with_stdio(0); cin.tie(0);
#define FOR(x,n,i) for(int i=x;i<=n;i++)
#define FOr(x,n,i) for(int i=x;i<n;i++)
#define fOR(n,x,i) for(int i=n;i>=x;i--)
#define fOr(n,x,i) for(int i=n;i>x;i--)
#define W while
#define sgn(x) ((x) < 0 ? -1 : (x) > 0)
#define bug printf("***********\n");
#define db double
#define ll long long
#define mp make_pair
#define pb push_back
typedef pair<long long int,long long int> ii;
typedef long long LL;
const int INF=0x3f3f3f3f;
const LL LINF=0x3f3f3f3f3f3f3f3fLL;
const int dx[]={-1,0,1,0,1,-1,-1,1};
const int dy[]={0,1,0,-1,-1,1,-1,1};
const int maxn=5e5+10;
const int maxx=600005;
const double EPS=1e-8;
const double eps=1e-8;
const int mod=1e9+7;
template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);}
template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);}
template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));}
template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));}
template <class T>
inline bool scan_d(T &ret){char c;int sgn;if (c = getchar(), c == EOF){return 0;}
while (c != '-' && (c < '0' || c > '9')){c = getchar();}sgn = (c == '-') ? -1 : 1;ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0' && c <= '9'){ret = ret * 10 + (c - '0');}ret *= sgn;return 1;}

inline bool scan_lf(double &num){char in;double Dec=0.1;bool IsN=false,IsD=false;in=getchar();if(in==EOF) return false;
while(in!='-'&&in!='.'&&(in<'0'||in>'9'))in=getchar();if(in=='-'){IsN=true;num=0;}else if(in=='.'){IsD=true;num=0;}
else num=in-'0';if(!IsD){while(in=getchar(),in>='0'&&in<='9'){num*=10;num+=in-'0';}}
if(in!='.'){if(IsN) num=-num;return true;}else{while(in=getchar(),in>='0'&&in<='9'){num+=Dec*(in-'0');Dec*=0.1;}}
if(IsN) num=-num;return true;}

void Out(LL a){if(a < 0) { putchar('-'); a = -a; }if(a >= 10) Out(a / 10);putchar(a % 10 + '0');}
void print(LL a){ Out(a),puts("");}
//freopen( "in.txt" , "r" , stdin );
//freopen( "data.txt" , "w" , stdout );
//cerr << "run time is " << clock() << endl;

int root,last;
int tots;  //总结点
int l;  //字符串长度

int sv[maxn*2];

int L[maxn],R[maxn];

struct sam_node
{
    int fa,son[180];
    int len;
    void init(int _len)
    {
        len = _len;
        fa = -1;
        memset(son,-1,sizeof(son));
    }
}t[maxn*2];

void sam_init()
{
    me(L,63);
    me(R,0);

    tots = 0;
    root = last = ++tots;
    t[tots].init(0);
}

void extend(int w)
{
    //int w=ch-'a';
    int p=last;
    int np=++tots;t[tots].init(t[p].len+1);
    sv[l]=np;
    L[np]=R[np]=t[np].len;
    int q,nq;
    while(p!=-1&&t[p].son[w]==-1){t[p].son[w]=np;p=t[p].fa;}
    if (p==-1) t[np].fa=root;
    else
    {
        q=t[p].son[w];
        if (t[p].len+1==t[q].len){t[np].fa=q;}
        else
        {
            nq=++tots;t[nq].init(0);
            t[nq]=t[q];
            t[nq].len=t[p].len+1;
            t[q].fa=nq;t[np].fa=nq;
            while(p!=-1&&t[p].son[w]==q){t[p].son[w]=nq;p=t[p].fa;}
        }
    }
    last=np;
}

int w[maxn*2], r[maxn*2];//w 一倍就够

void topsort()
{
    for(int i = 0; i <= l; ++i) w[i] = 0;
    for(int i = 1; i <= tots; ++i) w[t[i].len]++;
    for(int i = 1; i <= l; ++i) w[i] += w[i-1];
    for(int i = tots; i >= 1; --i) r[w[t[i].len]--] = i;
    r[0] = 0;
}

int dp[maxn*2];
char s[maxn];

int op,k,p;
int sum[maxn*2];

bool cmp(int a,int b)
{
    return t[a].len>t[b].len;
}

void work()
{
    int ans=0;
    FOR(1,tots,i)
        w[i]=i;
    sort(w+1,w+tots,cmp);
    FOR(1,tots,i)
    {
        L[t[w[i]].fa]=min(L[t[w[i]].fa],L[w[i]]);
        R[t[w[i]].fa]=max(R[t[w[i]].fa],R[w[i]]);
    }
    FOR(1,tots,i)
        ans=max(ans,min(t[i].len,R[i]-L[i]));
    printf("%d\n",ans<4?0:ans+1);
}

int a[maxn];
int main()
{
    //freopen( "in.txt" , "r" , stdin );
    W(s_1(l)!=EOF,l)
    {
        FOR(1,l,i)
            s_1(a[i]);
        FOr(1,l,i)
            a[i]=a[i+1]-a[i]+88;
        sam_init();
        FOR(1,l,i)
            extend(a[i]);
        work();
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值