CF700E Cool Slogans 后缀自动机 + right集合线段树合并 + 树形DP

又是一道 SAM 神题.

Code: 

#include<bits/stdc++.h>
#define maxn 400002 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;   
namespace tr 
{
    #define lson t[x].l 
    #define rson t[x].r 
    #define mid ((l+r)>>1) 
    int cnt; 
    struct Node { int l,r; }t[maxn*20]; 
    void modify(int &x,int l,int r,int k)
    {
        if(!x) x=++cnt; 
        if(l==r) return; 
        if(k<=mid) modify(lson,l,mid,k); 
        else modify(rson,mid+1,r,k); 
    }
    int merge(int u,int v) 
    {
        if(!u||!v) return u+v; 
        int x=++cnt; 
        lson=merge(t[u].l,t[v].l); 
        rson=merge(t[u].r,t[v].r);    
        return x;             
    }
    int query(int x,int l,int r,int L,int R)
    {
        if(!x) return 0; 
        if(l>=L&&r<=R) return 1; 
        int tmp=0; 
        if(L<=mid) tmp+=query(lson,l,mid,L,R); 
        if(R>mid) tmp+=query(rson,mid+1,r,L,R); 
        return tmp; 
    }
}; 
namespace SAM 
{ 
    char str[maxn]; 
    int last,tot,n;  
    int trans[maxn][27],f[maxn],len[maxn],C[maxn],rk[maxn],top[maxn],dp[maxn],pos[maxn],rt[maxn];  
    void init() { last=tot=1; }
    void extend(int c,int i) 
    {  
        int np=++tot,p=last; 
        len[np]=len[p]+1,last=np; 
        while(p&&!trans[p][c]) trans[p][c]=np,p=f[p]; 
        if(!p) f[np]=1; 
        else 
        {
            int q=trans[p][c]; 
            if(len[q]==len[p]+1) f[np]=q; 
            else 
            {
                int nq=++tot; 
                len[nq]=len[p]+1; 
                pos[nq]=pos[q];  
                memcpy(trans[nq],trans[q],sizeof(trans[q])); 
                f[nq]=f[q], f[np]=f[q]=nq; 
                while(p&&trans[p][c]==q) trans[p][c]=nq,p=f[p]; 
            }
        }
        pos[np]=i; 
        tr::modify(rt[last],1,n,i);   
    }
    void prepare() 
    {
        int i,j; 
        init(); 
        scanf("%d%s",&n,str+1);  
        for(i=1;i<=n;++i) extend(str[i]-'a',i);  
        for(i=1;i<=tot;++i) ++C[len[i]]; 
        for(i=1;i<=tot;++i) C[i]+=C[i-1]; 
        for(i=1;i<=tot;++i) rk[C[len[i]]--]=i;    
        for(i=tot;i>1;--i) 
        {
            int u=rk[i]; 
            rt[f[u]]=tr::merge(rt[f[u]],rt[u]);  
        }                     
    }
    void calc() 
    {
        int i,j,ans=1; 
        for(i=2;i<=tot;++i) 
        {
            int u=rk[i],ff=f[rk[i]];  
            if(ff==1) { top[u]=u,dp[u]=1; continue; }  
            if(tr::query(rt[top[ff]],1,n,pos[u]-len[u]+len[top[ff]],pos[u]-1))
                top[u]=u,dp[u]=dp[top[ff]]+1; 
            else 
                top[u]=top[ff];       
            ans=max(ans,dp[u]);                 
        }
        printf("%d\n",ans);  
    }
}; 
int main()
{
    //msetIO("input"); 
    SAM::prepare();                  
    SAM::calc(); 
    return 0; 
}

  

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值