• 【[SDOI2008]Sandy的卡片】


    (mhr)的暴力干翻了

    这道题做法还是非常好想的

    先做一遍差分,在每个串的某尾插入一个特殊字符,再将所有的串拼接在一起

    现在的问题就转化为找到一个最长的公共子串使得其出现了(n)次,但是在一个串内出现多次出现只算一次

    先考虑一下没有第二个限制的做法

    那就是最简单的(SA)+二分了,就是扫一遍(height)数组,之后根据(height)进行分组使得一个组内所有的(height)都大于等于当前二分出来的(mid),之后一个组内有多少个就代表这个子串出现了多少次

    现在有了限制,就是不能来自于同一个串

    于是我们给每一个(sa_i)打一个标记,标记好其来自哪一个数组,之后对于一个组内出现的同一个串内的我们只需要算一次就够了

    代码

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define re register
    #define LL long long
    #define maxn (1000*100+1000+5)*2
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    #define pt putchar(1)
    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;
    }
    int a[maxn],f[maxn],c[maxn];
    int tp[maxn],sa[maxn],rk[maxn],tax[maxn],het[maxn],b[maxn];
    int n,m,K,r,t;
    inline void qsort()
    {
    	for(re int i=0;i<=K;i++) tax[i]=0;
    	for(re int i=1;i<=n;i++) tax[rk[i]]++;
    	for(re int i=1;i<=K;i++) tax[i]+=tax[i-1];
    	for(re int i=n;i;--i) sa[tax[rk[tp[i]]]--]=tp[i];
    }
    inline int check(int x)
    {
    	int num=0,now=1;
    	if(f[sa[1]]) num++,b[f[sa[1]]]++;
    	for(re int i=2;i<=n;i++)
    	{
    		if(het[i]<x)
    		{
    			if(num>=m) return 1;
    			for(re int j=now;j<i;j++) b[f[sa[j]]]=0;
    			num=0,now=i;
    			if(f[sa[i]]) num++,b[f[sa[i]]]++;
    			continue;
    		}
    		if(!b[f[sa[i]]]&&f[sa[i]]) b[f[sa[i]]]++,num++;
    	}
    	return num>=m;
    }
    int main()
    {
    	m=read();
    	for(re int i=1;i<=m;i++)
    	{
    		t=read();r=max(t,r);
    		for(re int j=1;j<=t;j++) a[++n]=read(),f[n]=i;
    		a[++n]=i+101,f[n]=0;
    	}
    	for(re int i=1;i<=n;i++) c[i]=a[i]-a[i-1];
    	for(re int i=1;i<=n;i++) c[i]+=2001,K=max(c[i],K);
    	c[1]=0;
    	for(re int i=1;i<=n;i++) tp[i]=i,rk[i]=c[i];
    	qsort();
    	for(re int w=1,p=0;p<n;K=p,w<<=1)
    	{
    		p=0;
    		for(re int i=1;i<=w;i++) tp[++p]=n-w+i;
    		for(re int i=1;i<=n;i++) if(sa[i]>w) tp[++p]=sa[i]-w;
    		qsort();
    		for(re int i=1;i<=n;i++) std::swap(rk[i],tp[i]);
    		rk[sa[1]]=p=1;
    		for(re int i=2;i<=n;i++) rk[sa[i]]=(tp[sa[i-1]]==tp[sa[i]]&&tp[sa[i-1]+w]==tp[sa[i]+w])?p:++p;
    	}
    	int k=0;
    	for(re int i=1;i<=n;i++)
    	{
    		if(k) --k;
    		int j=sa[rk[i]-1];
    		while(c[i+k]==c[j+k]) ++k;
    		het[rk[i]]=k;
    	}
    	int l=1,ans=0;
    	while(l<=r)
    	{
    		int mid=l+r>>1;
    		if(check(mid)) l=mid+1,ans=mid;
    			else r=mid-1;
    	}
    	printf("%d
    ",ans+1);
     	return 0;
    }
    
  • 相关阅读:
    ASP.NET Post方式提交
    MVC增加操作日志
    asp.net MVC 下拉多级联动及编辑
    redis基本数据类型之String
    关于idea下使用springinitializr创建项目时 初始化失败的解决
    Failed to read artifact descriptor for org.mybatis:mybatis:jar:2.2.1
    如何查看日志文件
    nginx 部署vue 以及同一端口下部署监听多个vue 项目
    JsonView 与JsonIgnore 使用
    vue 打包部署
  • 原文地址:https://www.cnblogs.com/asuldb/p/10205635.html
Copyright © 2020-2023  润新知