zoukankan      html  css  js  c++  java
  • POJ 2217 Secretary(后缀数组+高度数组)

    题目链接:

    2217 Secretary

    思路:

    将两个字符串用一个不会出现的字符,如$连接起来,然后求此字符串的高度数组,从前往后遍历所有i,当sa[i]sa[i+1即两个子串的起始位置在两个不同的字符串中时(即我们相加的这两个字符串),此时iheight即为公共子串长度,我们找到最大值即可

    代码:

    #include<iostream>
    #include<string>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=2e4+99;
    string s,a,b;
    int n,k,sa[maxn],rk[maxn],tmp[maxn],lcp[maxn];
    bool cmp(const int& i,const int& j){
    	if(rk[i]!=rk[j]) return rk[i]<rk[j];
    	else{
    		int ri=i+k<=n?rk[i+k]:-1;
    		int rj=j+k<=n?rk[j+k]:-1;
    		return ri<rj;
    	}
    }
    void cal_sa(){
    	n=s.length(); 
    	for(int i=0;i<=n;i++) sa[i]=i,rk[i]=s[i]; rk[n]=0;
    	for(k=1;k<=n;k<<=1){
    		sort(sa,sa+n+1,cmp);
    		tmp[sa[0]]=0;
    		for(int i=1;i<=n;i++){
    			tmp[sa[i]]=tmp[sa[i-1]]+(cmp(sa[i-1],sa[i])?1:0);
    		}
    		for(int i=0;i<=n;i++) rk[i]=tmp[i];
    	}
    }
    void cal_lcp(){
    	for(int i=0;i<=n;i++) rk[sa[i]]=i;
    	int h=0; lcp[0]=0;
    	for(int i=0;i<n;i++){
    		int j=sa[rk[i]-1];
    		if(h) --h;
    		while(j+h<n&&i+h<n&&s[j+h]==s[i+h]) h++;
    		lcp[rk[i]-1]=h;
    	}
    }
    void solve(){
    	s=a+'$'+b; cal_sa(); cal_lcp();
    	int ans=0,len=a.length();
    	for(int i=0;i<s.length();i++){
    		if((sa[i]<len)!=(sa[i+1]<len)) ans=max(ans,lcp[i]);
    	}
    	cout<<"Nejdelsi spolecny retezec ma delku "<<ans<<".
    ";
    }
    int main(){
    	ios::sync_with_stdio(false); cin.tie(0);
    	int kase; cin>>kase; getline(cin,s);
    	while(kase--){
    		getline(cin,a); getline(cin,b);
    		solve();
    	}
    	return 0;
    }
    
  • 相关阅读:
    Delegte的BeginInvoke
    C# socket 实现客户端连续发送数据
    Button的PerformClick()
    Invoke和BeginInvoke
    Application.DoEvents() 处理队列消息,防界面假死
    BackgroundWorker后台线程
    CF773F
    ORM框架,没必要搞那么复杂
    VS Unable to copy file
    Unbuntu auto start program
  • 原文地址:https://www.cnblogs.com/yuhan-blog/p/12308726.html
Copyright © 2011-2022 走看看