zoukankan      html  css  js  c++  java
  • P2463 [SDOI2008]Sandy的卡片

    P2463 [SDOI2008]Sandy的卡片

    差分过后就是求最长公共子串了,无数多倍经验了...

    具体可以见P5546 [POI2000]公共串

    但是这道题要魔改一下就是:

    (1.) 第一项可以不匹配,于是输出 (ans+1)

    (2.) 因为这里值域很大,所以用 (map) 代替数组。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    template <typename T>
    inline void read(T &x){
    	x=0;char ch=getchar();bool f=false;
    	while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
    	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    	x=f?-x:x;
    	return ;
    }
    template <typename T>
    inline void write(T x){
    	if(x<0) putchar('-'),x=-x;
    	if(x>9) write(x/10);
    	putchar(x%10^48);
    	return ;
    }
    const int N=3e5+5,INF=1e9+7;
    int x,n,a[N],last=1,tot=1,Ans[N<<1],AAns[N<<1],ans,c[N],q[N<<1];
    bool flag;
    char str[N];
    struct SAM{
    	unordered_map<int,int>son;
    	int fa,len;
    }t[N<<1];
    void Extend(int c){
    	int p=last,np=++tot;last=np;
    	t[np].len=t[p].len+1;
    	while(p&&!t[p].son[c]) t[p].son[c]=np,p=t[p].fa;
    	if(!p) t[np].fa=1;
    	else{
    		int q=t[p].son[c];
    		if(t[p].len+1==t[q].len) t[np].fa=q;
    		else{
    			int nq=++tot;
    			t[nq]=t[q];t[nq].len=t[p].len+1;
    			t[np].fa=t[q].fa=nq;
    			while(p&&t[p].son[c]==q) t[p].son[c]=nq,p=t[p].fa;
    		}
    	}
    	return ;
    }
    int Len;
    void Search(int &x,int c){
    	if(t[x].son[c]) Len++,x=t[x].son[c],AAns[x]=max(AAns[x],Len);
    	else{
    		int p=x;
    		while(p&&!t[p].son[c]) p=t[p].fa;
    		if(!p) x=1,Len=0;
    		else x=t[p].son[c],Len=t[p].len+1,AAns[x]=max(AAns[x],Len);
    	}
    	return ;
    }
    int main(){
    	read(n);
    	int len;read(len);
    	for(int i=1;i<=len;i++) read(a[i]);
    	for(int i=1;i<=len;i++) Extend(a[i]-a[i-1]);
    	for(int i=1;i<=tot;i++) c[t[i].len]++;
    	for(int i=1;i<=tot;i++) c[i]+=c[i-1];
    	for(int i=1;i<=tot;i++) q[c[t[i].len]--]=i;
    	for(int i=0;i<=tot;i++) Ans[i]=INF;
    	n--;
    	while(n--){
    		read(len);
    		for(int i=1;i<=len;i++) read(a[i]);
    		for(int i=1,now=1;i<=len;i++) Search(now,a[i]-a[i-1]);
    		for(int i=tot;i>=1;i--){
    			int x=q[i];
    			AAns[t[x].fa]=max(AAns[t[x].fa],min(AAns[x],t[t[x].fa].len));
    			Ans[x]=min(Ans[x],AAns[x]);AAns[x]=0;
    		}
    	}
    	for(int i=1;i<=tot;i++) ans=max(ans,Ans[i]);
    	write(ans+1);
    	return 0;
    }
    
  • 相关阅读:
    StopAllSounds
    GotoAndPlay
    区间(interval)
    因数(factor)
    [HAOI2009]逆序对数列
    生物分子gene
    数轴line
    [SCOI2008]配对
    精力(power)
    bzoj4987: Tree(树形dp)
  • 原文地址:https://www.cnblogs.com/Akmaey/p/14691284.html
Copyright © 2011-2022 走看看