zoukankan      html  css  js  c++  java
  • 【后缀数组】poj2406 Power Strings

    连续重复子串(pku2406)
    给定一个字符串 L,已知这个字符串是由某个字符串 S 重复 R 次而得到的,
    求 R 的最大值。
    算法分析:
    做法比较简单,穷举字符串 S 的长度 k,然后判断是否满足。判断的时候,
    先看字符串 L 的长度能否被 k 整除,再看 suffix(1)和 suffix(k+1)的最长公共
    前缀是否等于 n-k。在询问最长公共前缀的时候, suffix(1)是固定的,所以 RMQ
    问题没有必要做所有的预处理,只需求出 height 数组中的每一个数到
    height[rank[1]]之间的最小值即可。整个做法的时间复杂度为 O(n)。

    卡倍增……

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define N 1000001
    char s[N];
    int n,tong[N],t[N],t2[N],sa[N],rank[N],lcp[N];
    bool cmp(int y[],int i,int k)
    {
    	return ((y[sa[i-1]]==y[sa[i]])&&((sa[i-1]+k>=n?-1:y[sa[i-1]+k])==(sa[i]+k>=n?-1:y[sa[i]+k])));
    }
    void build_sa(int range)
    {
    	int *x=t,*y=t2;
    	memset(tong,0,sizeof(int)*range);
    	for(int i=0;i<n;++i) tong[x[i]=s[i]]++;
    	for(int i=1;i<range;++i) tong[i]+=tong[i-1];
    	for(int i=n-1;i>=0;--i) sa[--tong[x[i]]]=i;
    	for(int k=1;k<=n;k<<=1)
    	  {
    	  	int p=0;
    	  	for(int i=n-k;i<n;++i) y[p++]=i;
    	  	for(int i=0;i<n;++i) if(sa[i]>=k) y[p++]=sa[i]-k;
    		memset(tong,0,sizeof(int)*range);
    		for(int i=0;i<n;++i) tong[x[y[i]]]++;
    		for(int i=1;i<range;++i) tong[i]+=tong[i-1];
    		for(int i=n-1;i>=0;--i) sa[--tong[x[y[i]]]]=y[i];
    	  	swap(x,y); p=1; x[sa[0]]=0;
    	  	for(int i=1;i<n;++i) x[sa[i]]=cmp(y,i,k)?p-1:p++;
    	  	if(p>=n) break;
    	  	range=p;
    	  }
    }
    void get_lcp()
    {
    	int k=0;
    	for(int i=0;i<n;++i) rank[sa[i]]=i;
    	for(int i=0;i<n;++i) if(rank[i])
    	  {
    	  	if(k) --k;
    	  	int j=sa[rank[i]-1];
    	  	while(s[i+k]==s[j+k]) ++k;
    	  	lcp[rank[i]]=k;
    	  }
    }
    int query[N];
    int main()
    {
    	while(1)
    	  {
    	  	scanf("%s",s);
    	  	if(s[0]=='.') break;
    	  	n=strlen(s);
    	  	build_sa(128);
    	  	get_lcp();
    	  	int minv=n-sa[rank[0]];
    	  	for(int i=rank[0];i>=0;--i)
    	  	  {
    	  	  	query[i]=minv;
    	  	  	minv=min(minv,lcp[i]);
    	  	  }
    	  	minv=lcp[rank[0]+1];
    	  	for(int i=rank[0]+1;i<n;++i)
    	  	  {
    	  	  	query[i]=minv;
    	  	  	minv=min(minv,lcp[i+1]);
    	  	  }
    	  	query[rank[n]]=0;
    	  	for(int i=1;i<=n;++i)
    	  	  if(n%i==0&&query[rank[i]]==n-i)
    	  	    {
    	  	      printf("%d
    ",n/i);
    	  	      break;
    	  	    }
    	  }
    	return 0;
    }
  • 相关阅读:
    oracle的根容器下新建pdb容器及本地用户
    oracle监听配置与防火墙问题
    oracle问题:ORA-09817及解决办法
    Oracle:Ora-01652无法通过128(在temp表空间中)扩展temp段的过程-解决步骤
    oracle:ORA-14765建索引阻塞创建分区及处理步骤
    oracle-组合索引字段位置与查询效率之间的关系
    hbase的split策略和预分区
    启动hbase后hmaster自动关闭
    hive一级分区、二级分区、动态分区
    hive beeline连接和交互shell连接
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/4462559.html
Copyright © 2011-2022 走看看