• [poj 3261]Milk Patterns


    后缀数组搞一下就可以了喵~

    其实这道题的第一个想法是 SAM ,建完后缀自动机后拓扑排序跑一遍统计下每个子串的出现次数就 O(N) 就妥妥过掉了

    后缀树也是 O(N) 的,统计一下每个节点对应的子树中有多少个叶子节点即可

    可是看了一下数据范围,欸呦你妹啊,字符数 1000000+1 是什么心态啊!居然把我的后缀树和后缀 zdj 都卡掉了啊!

    然后很痛苦的想了想后缀数组的做法:

    搞出 sa, rank, height 三个数组后,跑一遍二分,用一个 tot 表示找到了几个子串

    二分答案 L,O(N) 扫个遍如果 height[i]>=L 说明又找到一个子串,tot++,否则重新计算

    不过注意这里 tot 的初始值是 1 而不是 0 

    不过这么个写法怎么写都是 O(NlogN) 的了,如果有更好的写法,请教我做人喵~

    #include <cstdio>
    #include <cstring>
    const int sizeOfN=20002;
    const int sizeOfType=1200021;
    
    namespace IOspace
    {
    	inline int getint()
    	{
    		register int num=0;
    		register char ch;
    		do ch=getchar(); while (ch<'0' || ch>'9');
    		do num=num*10+ch-'0', ch=getchar(); while (ch>='0' && ch<='9');
    		return num;
    	}
    	inline void putint(int num)
    	{
    		char stack[15];
    		register int top=0;
    		if (num==0) stack[top=1]='0';
    		for ( ;num;num/=10) stack[++top]=num%10+'0';
    		for ( ;top;top--) putchar(stack[top]);
    		putchar('
    ');
    	}
    }
    
    int N, K;
    int A[sizeOfN];
    
    namespace suffixArray
    {
    	int sa[sizeOfN], rank[sizeOfN], height[sizeOfN];
    
    	inline void swap(int *& x, int *& y) {int * t=x; x=y; y=t;}
    	inline void buildArray()
    	{
    		static int t[2][sizeOfN];
    		static int c[sizeOfType];
    		int * x=t[0], * y=t[1];
    		int M=sizeOfType;
    
    		for (int i=0;i<M;i++) c[i]=0;
    		for (int i=0;i<N;i++) c[x[i]=A[i]]++;
    		for (int i=1;i<M;i++) c[i]+=c[i-1];
    		for (int i=N-1;i>=0;i--) sa[--c[x[i]]]=i;
    
    		for (int j=0, k=1;j<N;M=j, k<<=1)
    		{
    			j=0;
    			for (int i=N-k;i<N;i++) y[j++]=i;
    			for (int i=0;i<N;i++) if (sa[i]>=k) y[j++]=sa[i]-k;
    
    			for (int i=0;i<M;i++) c[i]=0;
    			for (int i=0;i<N;i++) c[x[y[i]]]++;
    			for (int i=1;i<M;i++) c[i]+=c[i-1];
    			for (int i=N-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
    
    			swap(x, y);
    			j=1; x[sa[0]]=0;
    			for (int i=1;i<N;i++)
    				x[sa[i]]=y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k]?j-1:j++;
    		}
    	}
    	inline void calcHeight()
    	{
    		int l=0;
    		for (int i=0;i<N;i++) rank[sa[i]]=i;
    		for (int i=0;i<N;i++)
    		{
    			int j=sa[rank[i]-1];
    			for (l=l?l-1:0;A[i+l]==A[j+l];l++);
    			height[rank[i]]=l;
    		}
    	}
    }
    
    inline int search();
    
    int main()
    {
    	N=IOspace::getint(), K=IOspace::getint();
    	for (int i=0;i<N;i++) A[i]=IOspace::getint()+1;
    	A[N++]=0;
    
    	suffixArray::buildArray();
    	suffixArray::calcHeight();
    
    	IOspace::putint(search());
    
    	return 0;
    }
    inline bool check(int l)
    {
    	int tot=1;
    	for (int i=1;i<N;i++)
    		if (suffixArray::height[i]>=l)
    		{
    			if (++tot>=K)
    				return true;
    		}
    		else
    			tot=1;
    
    	return false;
    }
    inline int search()
    {
    	int L=0, R=N, M;
    
    	while (L+1<R)
    	{
    		M=(L+R)>>1;
    		if (check(M)) L=M;
    		else R=M;
    	}
    
    	return L;
    }
    

    机房里把 插入代码(推荐) 给卡了真是 sang xin bing kuang!我要申诉!

  • 相关阅读:
    RDD的五个属性
    惰性求值的概念
    大数据shuffle的理解
    简单说明hadoop和hbase的异同
    Linux 下命令有哪几种可使用的通配符?分别代表什么含义?
    linux命令知识点复习
    >/dev/null 2>&1
    JAVA内存泄漏和内存溢出的区别和联系
    Linux各个目录的作用
    JVM标准参数-server与-client参数的区别
  • 原文地址:https://www.cnblogs.com/dyllalala/p/3930073.html
Copyright © 2020-2023  润新知