• POJ 2774 Long Long Message (后缀数组)


    传送门

    题意

    计算两个字符串的最长公共子串

    思路

    将问题转化为找两个后缀的最长公共前缀
    将两个字符串拼接在一起,用'#'隔开,然后走一个后缀数组,利用 (height[i]) 更新答案,
    要注意两个后缀不能在一个串里面,所以要记录'#'分割符的位置,在更新答案之前看 (sa[i]) 和 $sa[i-1] $ 是否是同一个串的后缀

    代码

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    using namespace std;
    const int MAXN=2e5+10;
    char s[MAXN],temp1[MAXN],temp2[MAXN];
    int n,m,ed,sa[MAXN],rk[MAXN*2],tp[MAXN*2],c[MAXN],ht[MAXN];
    
    void getsa(){
    	m='z';
    	for(int i=1;i<=n;i++) c[rk[i]=s[i]]++;
    	for(int i=1;i<=m;i++) c[i]+=c[i-1];
    	for(int i=1;i<=n;i++) sa[c[rk[i]]--]=i;
    	for(int w=1,p=0;p<n;w<<=1,m=p){
    		p=0;
    		for(int i=n-w+1;i<=n;i++) tp[++p]=i;
    		for(int i=1;i<=n;i++) if(sa[i]>w) tp[++p]=sa[i]-w;
    		for(int i=1;i<=m;i++) c[i]=0;
    		for(int i=1;i<=n;i++) c[rk[i]]++;
    		for(int i=1;i<=m;i++) c[i]+=c[i-1];
    		for(int i=n;i>=1;i--) sa[c[rk[tp[i]]]--]=tp[i];
    		swap(rk,tp);
    		rk[sa[1]]=p=1;
    		for(int i=2;i<=n;i++)
    			rk[sa[i]]=(tp[sa[i]]==tp[sa[i-1]]&&tp[sa[i]+w]==tp[sa[i-1]+w])?p:++p;
    	}
    }
    
    void getheight(){
    	int k=0;
    	for(int i=1;i<=n;i++){
    		if(rk[i]==1) continue;
    		if(k) k--;
    		int j=sa[rk[i]-1];
    		while(j+k<=n&&i+k<=n&&s[j+k]==s[i+k]) k++;
    		ht[rk[i]]=k;
    	}
    }
    
    int main(){
    	scanf("%s%s",temp1,temp2);
    	ed=strlen(temp1)+1;
    	sprintf(s+1,"%s#%s",temp1,temp2);
    	n=strlen(s+1);
    	getsa();
    	getheight();
    	int ans=0;
    	for(int i=2;i<=n;i++)
    		if(sa[i]<ed&&sa[i-1]>ed||sa[i]>ed&&sa[i-1]<ed)
    			ans=max(ans,ht[i]);
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    浅谈社交网络中的用户心理
    QQ公众号&微信公众号,左右互搏?
    双11预售不能无理由退货?
    大数据:70多个网站让你免费获取大数据存储库
    雜項.筆記
    字母源流
    心經日語讀法
    throttle與debounce算法的邏輯
    解決中英混合輸入時標點切換問題的辦法
    漢譯Promises/A+規範
  • 原文地址:https://www.cnblogs.com/BakaCirno/p/11983216.html
Copyright © 2020-2023  润新知