• 后缀数组的使用心得——POJ2774 最长连续公共子串


    对于这道题,将两个字符串直接合并成为一个字符串,分别记录连个字符串结束的位置。

    首先,应用黑暗圣典的模板,我们可以顺利得到height,rank,sa三个数组。

    之后直接扫描1-n所有的位置,选出来一个,符合“两者都在不同子串的最大长度即可”。

    此时我们会发现,sa数组记录了每个子串开头的位置,可以用于判断。

    #include<iostream>
    #include<stdio.h>
    #include<string>
    #include<string.h>
    #include<vector>
    #include<algorithm>
    using namespace std;
    
    const long long MAXN=200233;
    const long long INF=1e8+233;
    char s[MAXN];
    int sa[MAXN],t[MAXN],t2[MAXN],c[MAXN],n;
    int rankk[MAXN],height[MAXN];
    void getHeight()
    {
        int k=0;
        for(int i=0;i<n;++i)rankk[sa[i]]=i;
        for(int i=0;i<n;++i)
        {
            if(k)k--;
            int j=sa[rankk[i]-1];
            while(s[i+k]==s[j+k])k++;
            height[rankk[i]]=k;
        }
    } 
    
    
    void build_sa(int m)
    {
        int i,*x=t,*y=t2;
        
        for(int i=0;i<m;++i)c[i]=0;
        for(int i=0;i<n;++i)c[x[i]=s[i]]++;
        for(int i=1;i<m;++i)c[i]+=c[i-1];
        for(int i=n-1;i>=0;--i)sa[--c[x[i]]]=i;
        for(int k=1;k<=n;k*=2)
        {
            int p=0;
            for(int i=n-k;i<n;++i)y[p++]=i;
            for(int i=0;i<n;++i)if(sa[i]>=k)y[p++]=sa[i]-k;
            
            for(int i=0;i<m;++i)c[i]=0;
            for(int i=0;i<n;++i)c[x[y[i]]]++;
            for(int i=0;i<m;++i)c[i]+=c[i-1];
            for(int i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];
            swap(x,y);
            p=1;x[sa[0]]=0;
            for(int i=1;i<n;++i)
            {
                x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
                 
            }
            if(p>=n)break;
            m=p;
        }
    }
    
     
    
    
    int main()
    {
    //    cin.sync_with_stdio(false);
        scanf("%s",s);
        int len=strlen(s);
        scanf("%s",s+len);
        int len2=strlen(s);
        n=len2+1;
        build_sa(233);
        getHeight();
        int maxx=-1;
        for(int i=1;i<n;++i)
        {
    //        cout<<height[i]<<ends<<s+sa[i]<<endl;    
            if((sa[i]>=len&&sa[i-1]<len)||(sa[i]<len&&sa[i-1]>=len))maxx=max(maxx,height[i]);
        }
        cout<<maxx<<"
    ";
    //    cout<<s<<endl;
    //    cout<<len<<ends<<len2<<endl;
    //    
        return 0;
    } 
  • 相关阅读:
    实验四Web服务器2
    发际线与我作队团队作业(五):冲刺总结1
    读书笔记
    socket3
    使用CAS来实现个单例模式
    基于无锁的C#并发队列实现
    C#3.0中的“多重继承”
    对并发/并行编程的总结
    谈谈多线程编程(二) 不变对象
    谈谈多线程编程(一) 安全性策略
  • 原文地址:https://www.cnblogs.com/rikka/p/7509181.html
Copyright © 2020-2023  润新知