• HihoCoder1415后缀数组三·重复旋律3


    重复旋律3

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

    描述

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

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

    输入

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

    输出

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

    样例输入
    abcdefg
    abacabca
    样例输出
    3

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn=210000;
    int Rank[maxn],cntA[maxn],cntB[maxn],A[maxn],B[maxn];
    int sa[maxn],tsa[maxn],ht[maxn];
    int ans,N,ch[maxn];
    char str1[maxn],str2[maxn];  
    void solve()
    {
        int i,j;
        for(i=1;i<=N;i++)  cntA[i]=0;
        for(i=1;i<=N;i++)  cntA[ch[i]]++;
        for(i=1;i<=N;i++)  cntA[i]+=cntA[i-1];
        for(i=N;i>=1;i--)  sa[cntA[ch[i]]--]=i;
        Rank[sa[1]]=1;
        for(i=2;i<=N;i++)  
        {
            Rank[sa[i]]=Rank[sa[i-1]];
            if(ch[sa[i]]!=ch[sa[i-1]]) Rank[sa[i]]++;
        }
        for(int L=1;Rank[sa[N]]<N;L<<=1)
        {
            for(i=0;i<=N;i++) cntA[i]=cntB[i]=0;
            for(i=1;i<=N;i++) cntA[A[i]=Rank[i]]++;
            for(i=1;i<=N;i++) cntB[B[i]=(i+L<=N)?Rank[i+L]:0]++;
            for(i=1;i<=N;i++) cntA[i]+=cntA[i-1];
            for(i=1;i<=N;i++) cntB[i]+=cntB[i-1];
            for(i=N;i>=1;i--) tsa[cntB[B[i]]--]=i;
            for(i=N;i>=1;i--) sa[cntA[A[tsa[i]]]--]=tsa[i];
            Rank[sa[1]]=1;
            for(i=2;i<=N;i++)
            {
                Rank[sa[i]]=Rank[sa[i-1]];
                if(A[sa[i]]!=A[sa[i-1]]||B[sa[i]]!=B[sa[i-1]]) Rank[sa[i]]++;
            }
        }
        for (i=1,j=0;i<=N;i++)
        {
            if(j) j --;
            while (ch[i+j]==ch[sa[Rank[i]-1]+j]) j++;
            ht[Rank[i]]=j;
        }
    }
    int main()
    {
        scanf("%s",str1+1);
        scanf("%s",str2+1);
        int L1=strlen(str1+1);
        int L2=strlen(str2+1);
        for(int i=1;i<=L1;i++) ch[i]=str1[i]-96;
        ch[L1+1]=30;
        for(int i=1;i<=L2;i++) ch[i+L1+1]=str2[i]-96;
        N=L1+L2+1; 
        solve();
        for(int i = 1; i <= N; i++)
        {
            if((sa[i]<=L1)!=(sa[i-1]<=L1))
                ans = max(ans, ht[i]);
        }
        printf("%d
    ",ans);
        return 0;
    }

    没有找到原因,开始用字符串一直错,改成数组就AC了。也不知道为什么。过几天再看看吧。

  • 相关阅读:
    SQL多表关联原理研究实验验证
    SQL多表关联原理研究实验验证
    vs2015如何设置不显示类或函数前的引用数量
    vs2015如何设置不显示类或函数前的引用数量
    Visual Studio 中突出显示的引用
    Visual Studio 中突出显示的引用
    GridControl标题及单元格内容居中显示
    GridControl标题及单元格内容居中显示
    DevExpress的GridControl控件设置自定义显示方法
    DevExpress的GridControl控件设置自定义显示方法
  • 原文地址:https://www.cnblogs.com/hua-dong/p/7860720.html
Copyright © 2020-2023  润新知