码迷,mamicode.com
首页 > 编程语言 > 详细

后缀数组三·重复旋律3

时间:2019-08-24 22:38:09      阅读:146      评论:0      收藏:0      [点我收藏+]

标签:tin   一个   单点   namespace   content   register   int   ababc   while   

#1415 : 后缀数组三·重复旋律3

时间限制:5000ms
单点时限:1000ms
内存限制:256MB

描述

小Hi平时的一大兴趣爱好就是演奏钢琴。我们知道一个音乐旋律被表示为长度为 N 的数构成的数列。小Hi在练习过很多曲子以后发现很多作品中的旋律有共同的部分。

旋律是一段连续的数列,如果同一段旋律在作品A和作品B中同时出现过,这段旋律就是A和B共同的部分,比如在abab 在 bababab 和 cabacababc 中都出现过。小Hi想知道两部作品的共同旋律最长是多少?

解题方法提示

输入

共两行。一行一个仅包含小写字母的字符串。字符串长度不超过 100000。

输出

一行一个整数,表示答案。

样例输入
abcdefg
abacabca
样例输出
3
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<cmath>
#include <bits/stdc++.h>
#include<vector>
typedef long long ll;
const int maxn=2e6+6;
using namespace std;
typedef std::pair<ll,ll> pll;
typedef std::string str;
int sa[maxn],rk[maxn],tp[maxn],height[maxn];
char s1[maxn],s2[maxn];
int ton[maxn],e[maxn],mx,n;
inline void rsort(){
    for(register int i=0;i<mx;++i)ton[i]=0;
    for(register int i=1;i<=n;++i)ton[rk[i]]++;
    for(register int i=1;i<=mx;++i)ton[i]=ton[i]+ton[i-1];
    for(register int i=n;i>=1;--i)sa[ton[rk[tp[i]]]--]=tp[i];
}
inline void solve(){
    for(register int i=1;i<=n;++i)rk[i]=e[i],tp[i]=i;
    rsort();
    for(register int w=1,p=0;w<=n&&p<n;w*=2,mx=p){
        p=0;
        for(register int i=n-w+1;i<=n;++i){
            tp[++p]=i;
        }
        for(register int i=1;i<=n;++i){
            if(sa[i]>w){
                tp[++p]=sa[i]-w;
            }
        }
        rsort();
        swap(rk,tp);
        rk[sa[1]]=p=1;
        for(register int i=2;i<=n;++i){
            rk[sa[i]]=(tp[sa[i-1]]==tp[sa[i]]&&tp[sa[i-1]+w]==tp[sa[i]+w])?p:++p;
        }
        if(p>=n)break;
    }
    int k=0;
    for(register int i=1;i<=n;++i){
        rk[sa[i]]=i;
    }
    for(register int i=1;i<=n;++i){
        if(k)k--;
        else k=0;
        int j=sa[rk[i]-1];
        while(e[i+k]==e[j+k])++k;
        height[rk[i]]=k;
    }
}
int main() {
    //freopen("1.txt","r",stdin);
    scanf("%s%s",s1+1,s2+1);
    int len1=strlen(s1+1),len2=strlen(s2+1);
    n=len1+len2+1;
    for(register int i=1;i<=len1;++i){
        e[i]=s1[i]-a+1;
        mx=max(mx,e[i]);
    }
    for(register int i=1;i<=len2;++i){
        e[i+len1+1]=s2[i]-a+1;
        mx=max(mx,e[i+len1+1]);
    }
    e[len1+1]=300;
    mx=max(mx,300);
    solve();
    int res=0;
//    for(register int i=1;i<=n;++i){
//        printf("debug rk[%d] = %d sa[%d] = %d height[%d] = %d\n",i,rk[i],i,sa[i],i,height[i]);
//    }
    for(register int i=2;i<=n;++i){
        if(sa[i]<=len1&&sa[i-1]<=len1)continue;
        if(sa[i]>len1&&sa[i-1]>len1)continue;
        res=max(res,height[i]);
    }
    printf("%d\n",res);
    return 0;
}
/*
 * abcdefg
   abacabca
 */

 

后缀数组三·重复旋律3

标签:tin   一个   单点   namespace   content   register   int   ababc   while   

原文地址:https://www.cnblogs.com/czy-power/p/11406120.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!