zoukankan      html  css  js  c++  java
  • hihocoder #1415 : 后缀数组三·重复旋律3

    #1415 : 后缀数组三·重复旋律3

    Time Limit:5000ms
    Case Time Limit:1000ms
    Memory Limit:256MB

    描述

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

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

    解题方法提示

    输入

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

    输出

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

    Sample Input
    abcdefg
    abacabca
    Sample Output
    3

    分析:

    把两个字符串接在一起就变成了求后缀的最长公共前缀的问题,但是由于这个前缀不能跨越两个字符串,所以我们在第一个字符串后面加上一个没有出现过的字符,再接第二个字符串,然后取所有非同一个串后缀的height的最大值...

    代码:

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    //by NeighThorn
    using namespace std;
    //zhao kan fei niao mu fei hui,ying chuang hua luo lian chui di
    
    const int maxn=200000+5;
    
    int n,t,s[maxn],gs[maxn],sa[maxn],wb[maxn],wv[maxn],ran[maxn],height[maxn];
    
    char s1[maxn],s2[maxn];
    
    inline bool cmp(int *x,int a,int b,int l){
    	return x[a]==x[b]&&x[a+l]==x[b+l];
    }
    
    inline void da(int *sa,int *x,int n,int m){
    	int i,j,p,*y=wb;
    	for(i=0;i<m;i++) gs[i]=0;
    	for(i=0;i<n;i++) gs[x[i]]++;
    	for(i=1;i<m;i++) gs[i]+=gs[i-1];
    	for(i=n-1;~i;i--) sa[--gs[x[i]]]=i;
    	for(j=1,p=1;p<n;j<<=1,m=p){
    		for(i=n-j,p=0;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++) gs[i]=0;
    		for(i=0;i<n;i++) gs[wv[i]]++;
    		for(i=1;i<m;i++) gs[i]+=gs[i-1];
    		for(i=n-1;~i;i--) sa[--gs[wv[i]]]=y[i];
    		p=1;swap(x,y);x[sa[0]]=0;
    		for(i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++;
    	}
    }
    
    inline void calheight(int n){
    	int i,j,k=0;
    	for(i=0;i<=n;i++) ran[sa[i]]=i;
    	for(i=0;i<n;height[ran[i++]]=k)
    		for(k?k--:233,j=sa[ran[i]-1];s[i+k]==s[j+k];k++);
    }
    
    inline int solve(int n){
    	int ans=0;
    	for(int i=1;i<=n;i++)
    		if((sa[i]<t&&sa[i-1]>t)||(sa[i]>t&&sa[i-1]<t))
    			ans=max(ans,height[i]);
    	return ans;
    }
    
    signed main(void){
    	scanf("%s%s",s1,s2);t=n=strlen(s1);
    	for(int i=0;i<n;i++) 
    		s[i]=s1[i]-'a'+1;
    	s[n]=100;int lala=strlen(s2);
    	for(int i=1;i<=lala;i++)
    		s[i+n]=s2[i-1]-'a'+1;n+=lala+1;
    	for(int i=0;i<n;i++)
    		ran[i]=s[i];
    	da(sa,ran,n+1,101);
    	calheight(n);
    	printf("%d
    ",solve(n));
    	return 0;
    }//Cap ou pas cap. Pas cap.
    

      


    By NeighThorn

  • 相关阅读:
    CodeForces 510C Fox And Names (拓扑排序)
    Codeforces 1153D Serval and Rooted Tree (简单树形DP)
    HDU 6437 Problem L.Videos (最大费用)【费用流】
    Luogu P3381 (模板题) 最小费用最大流
    Codeforces 741B Arpa's weak amphitheater and Mehrdad's valuable Hoses (并查集+分组背包)
    Codeforces 1144F Graph Without Long Directed Paths (DFS染色+构造)
    HDU 2204 Eddy's 爱好 (容斥原理)
    Codeforces 939E Maximize! (三分 || 尺取)
    Codeforces 938D. Buy a Ticket (最短路+建图)
    CodeForces 959E Mahmoud and Ehab and the xor-MST (MST+找规律)
  • 原文地址:https://www.cnblogs.com/neighthorn/p/6295216.html
Copyright © 2011-2022 走看看