• ural1517


    题解:

    后缀数组

    求一下最长公共字串

    代码:

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring> 
    using namespace std;  
    const int N=2000200;  
    char s1[N],m,n,s2[N],ss[N]; 
    int height[N],str[N],sa[N],Log[N],best[23][N],rank[N],c[N],t1[N],t2[N];  
    void da(int *str,int n,int m)  
    {  
        int *x=t1,*y=t2;  
        for (int i=0;i<m;i++)c[i]=0;  
        for (int i=0;i<n;i++)c[x[i]=str[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<<=1)  
         {  
            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=1;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]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++;  
            if (p>=n)break;  
            m=p;  
         }  
    }  
    void calheight(int *str,int n)  
    {  
        int j,k=0;  
        for (int i=0;i<=n;i++)rank[sa[i]]=i;  
        for (int i=0;i<n;i++)  
         {  
            if (k)k--;  
            j=sa[rank[i]-1];  
            while (str[i+k]==str[j+k])k++;  
            height[rank[i]]=k;  
         }  
    }  
    void init(int n)  
    {   
        Log[0]=-1;  
        for (int i=1;i<=n;i++)Log[i]=(i&(i-1))?Log[i-1]:Log[i-1]+1;  
        for (int i=1;i<=n;i++)best[0][i]=height[i];  
        for (int i=1;i<=Log[n];i++)  
         for (int j=1;j<=n;j++)best[i][j]=min(best[i-1][j],best[i-1][j+(1<<(i-1))]);  
    }  
    int lcp(int a,int b)  
    {  
        a=rank[a];  
        b=rank[b];  
        if (a>b)swap(a,b);  
        a++;  
        int t=Log[b-a+1];  
        return min(best[t][a],best[t][b-(1<<t)+1]);  
    }  
    int main()  
    {   
        while (~scanf("%d",&m))  
         {  
            scanf("%s%s",s1,s2);  
            int l1=strlen(s1);  
            int l2=strlen(s2);  
            int len=0;  
            for (int i=0;i<l1;i++)str[len++]=s1[i];  
            str[len++]=1;  
            for (int i=0;i<l2;i++)str[len++]=s2[i];  
            str[len]=0;  
            da(str,len+1,300);  
            calheight(str,len);  
            int be,ans=0;  
            for (int i=1;i<=len;i++)  
             {  
                if ((sa[i]<l1&&sa[i-1]>l1)||(sa[i]>l1&&sa[i-1]<l1))  
                if (ans<height[i])ans=height[i],be=sa[i];  
             }  
            for (int i=be;i<be+ans;i++)putchar(str[i]);  
            puts("");  
         }  
        return 0;  
    }  
  • 相关阅读:
    【原创】枚举Android系统的进程、任务和服务的信息
    WPF学习笔记“控件”一:控件基本属性
    WCF学习笔记:基础一
    WPF学习笔记“布局”三:Grid分割窗口
    WPF学习笔记“XAML”一:基础
    WPF学习笔记“窗口”一:入门
    WPF学习笔记“形状”:基础
    WPF学习笔记“窗口”二:入门
    WPF学习笔记“窗口”四:三种方式不规则窗口实现大小的改变
    WPF学习笔记“窗口”三:入门
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/8550927.html
Copyright © 2020-2023  润新知