zoukankan      html  css  js  c++  java
  • CF700E Cool Slogans

    题目

    (yyb)代码真是开心的一批

    这道题看上去确实是没有什么思路

    之后想一想大概是在(parent)树上从儿子向父亲转移

    但是好像不太对的样子

    于是考虑在(parent)树上从父亲向儿子转移

    显然父亲一定是儿子的一个后缀,于是父亲肯定在儿子里出现了一次

    至于如何保证其出现第二次呢,我们可以用线段树合并来维护

    用线段树合并来维护一下(endpos)集合,看一下父亲有没有在儿子里出现过两次就好了

    代码

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #define re register
    #define maxn 400005
    #define M 8000005
    #define LL long long
    #define inf 999999999
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    inline int read()
    {
    	char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    char S[maxn];
    int fa[maxn],len[maxn],son[maxn][26],rt[maxn],top[maxn],pos[maxn],dp[maxn];
    int tax[maxn],A[maxn]; 
    int l[M],r[M],d[M];
    int n,tot,lst=1,cnt=1,ans=1;
    int change(int now,int x,int y,int pos)
    {
    	if(!now) now=++tot;d[now]++;
    	if(x==y) return now;
    	int mid=x+y>>1;
    	if(pos<=mid) l[now]=change(l[now],x,mid,pos);
    		else r[now]=change(r[now],mid+1,y,pos);
    	return now; 
    }
    int merge(int a,int b,int x,int y)
    {
    	if(!a) return b;if(!b) return a;
    	int root=++tot;
    	if(x==y) {d[root]=d[a]+d[b];return root;}
    	int mid=x+y>>1; 
    	l[root]=merge(l[a],l[b],x,mid);r[root]=merge(r[a],r[b],mid+1,y);
    	d[root]=d[l[root]]+d[r[root]];
    	return root;
    }
    inline void ins(int c,int o)
    {
    	int p=++cnt,f=lst; lst=p;
    	len[p]=len[f]+1,rt[p]=change(rt[p],1,n,o),pos[p]=o;
    	while(f&&!son[f][c]) son[f][c]=p,f=fa[f];
    	if(!f) {fa[p]=1;return;}
    	int x=son[f][c];
    	if(len[f]+1==len[x]) {fa[p]=x;return;}
    	int y=++cnt;
    	len[y]=len[f]+1,fa[y]=fa[x],fa[x]=fa[p]=y;
    	for(re int i=0;i<26;i++) son[y][i]=son[x][i];
    	while(f&&son[f][c]==x) son[f][c]=y,f=fa[f];
    }
    int query(int now,int x,int y,int lx,int ry)
    {
    	if(!now) return 0;
    	if(lx<=x&&ry>=y) return d[now]>0;
    	int mid=x+y>>1;
    	if(ry<=mid) return query(l[now],x,mid,lx,ry);
    	if(lx>mid) return query(r[now],mid+1,y,lx,ry);
    	return query(l[now],x,mid,lx,ry)|query(r[now],mid+1,y,lx,ry);
    }
    int main()
    {
    	scanf("%d",&n);scanf("%s",S+1);
    	for(re int i=1;i<=n;i++) ins(S[i]-'a',i);
    	for(re int i=1;i<=cnt;i++) tax[len[i]]++;
    	for(re int i=1;i<=n;i++) tax[i]+=tax[i-1];
    	for(re int i=1;i<=cnt;i++) A[tax[len[i]]--]=i;
    	for(re int i=cnt;i>1;--i) 
    		rt[fa[A[i]]]=merge(rt[fa[A[i]]],rt[A[i]],1,n),pos[fa[A[i]]]=max(pos[fa[A[i]]],pos[A[i]]);
    	for(re int i=2;i<=cnt;i++)
    	{
    		int x=A[i];
    		if(fa[x]==1) {dp[x]=1;top[x]=x;continue;}
    		int now=query(rt[top[fa[x]]],1,n,pos[x]-len[x]+len[top[fa[x]]],pos[x]-1);
    		if(now) dp[x]=dp[fa[x]]+1,top[x]=x;
    			else dp[x]=dp[fa[x]],top[x]=top[fa[x]];
    		ans=max(ans,dp[x]);
    	} 
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    485串口接线
    mvc3 升级mvc5
    VB连接ACCESS数据库,使用 LIKE 通配符问题
    VB6 读写西门子PLC
    可用的 .net core 支持 RSA 私钥加密工具类
    解决 Win7 远程桌面 已停止工作的问题
    解决 WinForm 重写 CreateParams 隐藏窗口以后的显示问题
    解决安装 .net framework 发生 extracting files error 问题
    CentOS7 安装配置笔记
    通过特殊处理 Resize 事件解决 WinForm 加载时闪烁问题的一个方法
  • 原文地址:https://www.cnblogs.com/asuldb/p/10333849.html
Copyright © 2011-2022 走看看