• poj1743 Musical Theme(后缀数组)


    题目求的是差分后的最长不重复相同子串

    利用后缀数组求解,首先答案具有二分性,也就是重复子串越大越好

    因此先二分最长长度,根据最长长度将所有后缀分组按height数组分组

    依据是height数组具有排名相邻的肯定是lcp最大的,而因此如果一段相邻的height数组的大小都大于等于二分值,这说明这段排名内的lcp都大于二分值

    这是因为假设i和j排名在这一段内那么答案就是height数组区间取min,显然都是大于二分值。反之一旦遇到height小于二分值就断开。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pll;
    const int N=2e5+10;
    const int inf=0x3f3f3f3f;
    int s[N],px[N];
    int n;
    int sa[N],rk[N],od[N],id[N],cnt[N],h[N],st[N][25];
    bool cmp(int x,int y,int w){
        return od[x]==od[y]&&od[x+w]==od[y+w];
    }
    int tmp[N];
    bool check(int len) {
        int mx = sa[1], mi = sa[1];
        for(int i = 2; i <= n; i++) {
            if(h[i]>=len)
                mx=max(sa[i], mx),
                mi=min(sa[i], mi);
             else
                mx=mi=sa[i];
            if(mx-mi>len) return 1;
        }
        return 0;
    }
    int main(){
        //ios::sync_with_stdio(false);
        while(cin>>n){
            if(n==0)
            break;
            int i;
            for(int i=1;i<=n;i++){
                scanf("%d",&s[i]);
            }
            for(i=1;i<=n;i++)
                s[i]=s[i+1]-s[i]+90;
            int m=max(n,300);
            memset(cnt,0,sizeof cnt);
            memset(h,0,sizeof h);
            memset(sa,0,sizeof sa);
            memset(rk,0,sizeof rk);
            memset(id,0,sizeof id);
            for(i=1;i<=n;i++) cnt[rk[i]=s[i]]++;
            for(i=1;i<=m;i++) cnt[i]+=cnt[i-1];
            for(i=n;i>=1;i--) sa[cnt[rk[i]]--]=i;
            int p;
            for(int w=1,p=0;w<n;w<<=1,m=p){
                for(p=0,i=n;i>n-w;i--){
                    id[++p]=i;
                }
                for(i=1;i<=n;i++){
                    if(sa[i]>w){
                        id[++p]=sa[i]-w;
                    }
                }
                memset(cnt,0,sizeof cnt);
                for(i=1;i<=n;i++) cnt[px[i]=rk[id[i]]]++;
                for(i=1;i<=m;i++) cnt[i]+=cnt[i-1];
                for(i=n;i>=1;i--) sa[cnt[px[i]]--]=id[i];
                memcpy(od,rk,sizeof rk);
                for(p=0,i=1;i<=n;i++){
                    rk[sa[i]]=cmp(sa[i],sa[i-1],w)?p:++p;
                }
            }
            for(i=1;i<=n;i++){
                if(rk[i]==1)
                    continue;
                int a=max(h[rk[i-1]]-1,0);
                while(i+a<=n&&s[i+a]==s[sa[rk[i]-1]+a])
                    a++;
                h[rk[i]]=a;
            }
            int l=0,r=n;
            while(l<r){
                int mid=l+r+1>>1;
                if(check(mid))
                    l=mid;
                else
                    r=mid-1;
            }
            if(l+1>=5){
                cout<<l+1<<endl;
            }
            else{
                cout<<0<<endl;
            }
        }
    }
    View Code
  • 相关阅读:
    数据库操作语句大全(sql)
    尚未在 Web 服务器上注册ASP.NET 4.5。安装VS15后的问题(转)
    ASP.NET通过http/https的POST方式,发送和接受XML文件内容(转)
    C# 的关键字详细介绍(转)
    12个css高级技巧.html
    CentOS上安装elasticsearch
    springboot例子
    ajax的XmlHttpRequest对象常用方法
    阿里云oss操作
    Python出现Could not find a version that satisfies the requirement openpyxl (from versions: )
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13297750.html
Copyright © 2020-2023  润新知