• POJ 2774 Long Long Message ——后缀数组


    【题目分析】

        用height数组RMQ的性质去求最长的公共子串。

        要求sa[i]和sa[i-1]必须在两个串中,然后取height的MAX。

        利用中间的字符来连接两个字符串的思想很巧妙,记得最后还需要空一个位置避免冲突。

    【代码】

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    
    #include <map>
    #include <set>
    #include <queue>
    #include <string>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    #define maxn 200005 
    #define inf 0x3f3f3f3f
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    
    void Finout()
    {
        #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    //    freopen("out.txt","w",stdout);
        #endif
    }
    
    int Getint()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    
    int tot=0,l1,l2;
    char s1[maxn],s2[maxn];
    
    struct Suf_Arr{
    	int s[maxn<<1],l;
    	int wa[maxn],wb[maxn],wv[maxn],ws[maxn];
    	int sa[maxn],rank[maxn],height[maxn];
    	int cmp(int *r,int a,int b,int l)
    	{return r[a]==r[b]&&r[a+l]==r[b+l];}
    	void getsa(int n,int m)
    	{
    		int i,j,p,*x=wa,*y=wb,*t;
    		for (i=0;i<m;++i) ws[i]=0;
    		for (i=0;i<n;++i) ws[x[i]=s[i]]++;
    		for (i=1;i<m;++i) ws[i]+=ws[i-1];
    		for (i=n-1;i>=0;--i) sa[--ws[x[i]]]=i;
    		for (j=1,p=1;p<n;j*=2,m=p)
    		{
    			for (p=0,i=n-j;i<n;++i) y[p++]=i;
    			for (i=0;i<n;++i) if (sa[i]>=j) y[p++]=sa[i]-j;
    			for (i=0;i<n;++i) wv[i]=x[y[i]];
    			for (i=0;i<m;++i) ws[i]=0;
    			for (i=0;i<n;++i) ws[wv[i]]++;
    			for (i=1;i<m;++i) ws[i]+=ws[i-1];
    			for (i=n-1;i>=0;--i) sa[--ws[wv[i]]]=y[i];
    			for (t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;++i)
    				x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    		}
    	}
    	void gethi(int n)
    	{
    		int i,j,k=0;
    		for (i=1;i<=n;++i) rank[sa[i]]=i;
    		for (int i=0;i<n;height[rank[i++]]=k)
    			for (k?k--:0,j=sa[rank[i]-1];s[i+k]==s[j+k];k++);
    	}
    	void build()
    	{
    		getsa(l+2,30);
    //		for (int i=0;i<=l;++i) cout<<sa[i]<<" "; cout<<endl;
    		gethi(l+1);
    	}
    	void solve()
    	{
    		int maxx=0;
    		for(int i=2;i<l;++i)
    			if (height[i]>maxx)
    			{
    				if (0<=sa[i-1]&&sa[i-1]<l1&&l1<sa[i]) maxx=height[i];
    				if (0<=sa[i]&&sa[i]<l1&&l1<sa[i-1]) maxx=height[i];
    			}
    		printf("%d
    ",maxx);
    	}
    }arr;
    
    int main()
    {
        Finout();
        scanf("%s",s1); scanf("%s",s2); 
        l1=strlen(s1); l2=strlen(s2); arr.l=l1+l2+1;
        for (int i=0;i<l1;++i) arr.s[i]=s1[i]-'a'+1;
        for (int i=0;i<l2;++i) arr.s[i+l1+1]=s2[i]-'a'+1;
        arr.s[l1+l2+1]=0; arr.s[l1]=28;
    //    printf("len is %d
    ",arr.l);
    //    for (int i=0;i<=arr.l;++i) cout<<(char)(arr.s[i]+'a'-1); cout<<endl;
        arr.build();
        arr.solve();
    }
    

      

  • 相关阅读:
    Linux下安装nginx
    使用Nginx搭建集群
    怎样解决虚拟机中多台机器之间的相互通信问题??
    怎样安装vmtools
    常用的机器学习&数据挖掘知识(点)领域链接
    sparkan安装链接
    matlab中怎样将散点用光滑曲线连接起来??
    matlab中怎样画出散点图,将这些散点连接成线??
    matlab中怎样计算两个集合的差集?-setdiff函数
    MATLAB中在一个三维矩阵中如何提取出一个二维矩阵,使用permute
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6246890.html
Copyright © 2020-2023  润新知