zoukankan      html  css  js  c++  java
  • ●SPOJ 8222 NSUBSTR–Substrings

    题链:

    http://www.spoj.com/problems/NSUBSTR/
    题解:

    后缀自动机。
    不难发现,对于自动机里面的一个状态s,
    如果其允许的最大长度为maxs[s],其right集合的大小为right[s],
    那么显然就可能对ANS[maxs[s]]造成贡献,即ANS[maxs[s]]=max(ANS[maxs[s]],right[s])
    最后再反向扫一遍ANS数组,从后向前取max即可。
    那么现在的问题就是如何求得right[]数组,即如何求出每个状态的right集合的大小。
    根据构造过程,首先给“主链”上的状态的right[]赋值为1,
    然后可以发现,虽然parent树并不好直接遍历,但是由于父亲状态的maxs一定小于儿子状态的maxs,
    所以使用桶排序对所有状态按maxs从大到小排序后,依次遍历每个状态,去给其父亲贡献即可求得right[]数组。
    整个过程是O(N)的。


    代码:

    #include<bits/stdc++.h>
    #define MAXN 250005
    using namespace std;
    int ANS[MAXN];
    struct SAM{
    	int size,last;
    	int maxs[MAXN*3],trans[MAXN*3][26],parent[MAXN*3],right[MAXN*3];
    	int Newnode(int a,int b){
    		++size; maxs[size]=a;
    		memcpy(trans[size],trans[b],sizeof(trans[b]));
    		return size;
    	}
    	void Extend(int x){
    		static int p,np,q,nq;
    		p=last; last=np=Newnode(maxs[p]+1,0);
    		for(;p&&!trans[p][x];p=parent[p]) trans[p][x]=np;
    		if(!p) parent[np]=1;
    		else{
    			q=trans[p][x];
    			if(maxs[p]+1!=maxs[q]){
    				nq=Newnode(maxs[p]+1,q);
    				parent[nq]=parent[q];
    				parent[q]=parent[np]=nq;
    				for(;p&&trans[p][x]==q;p=parent[p]) trans[p][x]=nq;
    			}
    			else parent[np]=q;
    		}
    	}
    	void Build(char *S){
    		memset(trans[0],0,sizeof(trans[0]));
    		size=0; last=Newnode(0,0);
    		for(int i=0;S[i];i++) Extend(S[i]-'a');
    	}
    	void Count_Right(char *S,int len){
    		static int p=1,tmp[MAXN],order[MAXN*3];
    		for(int i=0;S[i];i++) p=trans[p][S[i]-'a'],right[p]=1;
    		for(int i=1;i<=size;i++) tmp[maxs[i]]++;
    		for(int i=1;i<=len;i++) tmp[i]+=tmp[i-1];
    		for(int i=size;i;i--) order[tmp[maxs[i]]--]=i;
    		for(int i=size;i;i--)
    			p=order[i],right[parent[p]]+=right[p];
    	}
    }SUF;
    int main(){
    	char S[MAXN]; int len;
    	scanf("%s",S); len=strlen(S);
    	SUF.Build(S);
    	SUF.Count_Right(S,len);
    	for(int i=1;i<=SUF.size;i++)
    		ANS[SUF.maxs[i]]=max(ANS[SUF.maxs[i]],SUF.right[i]);
    	for(int i=len;i;i--) ANS[i]=max(ANS[i],ANS[i+1]);
    	for(int i=1;i<=len;i++) printf("%d
    ",ANS[i]);
    	return 0;
    }
    

      

  • 相关阅读:
    uva 442 Matrix Chain Multiplication
    结对编程项目之队友代码分析
    [转] 为什么要使用NoSQL
    Compare Linq2Sql with NHibernate
    使用linq2sql 的DetailView 如何保存多对多关系
    工作流入门
    XML字段的用处
    DesignTimeResourceProviderFactory 不给力啊
    如何给XMLDatasource做分页和排序
    ORM的烦恼
  • 原文地址:https://www.cnblogs.com/zj75211/p/8541815.html
Copyright © 2011-2022 走看看