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;
    }
    
  • 相关阅读:
    Linux服务器管理: 系统的定时任务crond
    Nmon的安装使用及获取报表
    笔记:LoadRunner性能测试巧匠训练营
    python-解决安装MySQL-python出现的: Python version 2.7 required,which was not found in the registry
    JMeter监控内存及CPU——plugin插件监控被测系统资源方法
    Linux监控
    SSL与TLS的区别以及介绍
    [存]Jmeter 如何实现跨线程组传递参数
    Robot Framework简介
    [转]Appium搭建六:安装Android模拟器
  • 原文地址:https://www.cnblogs.com/asuldb/p/10333849.html
Copyright © 2011-2022 走看看