您的位置:首页 > Web前端

UVa11107 Lifeform

2016-05-06 16:33 113 查看

题目链接

UVa11107 Lifeform

题解

学了高大上的后缀数组但是还是不怎么会用,关键是版子最开始打错了,害得我必须再重新理解一遍才能找出bug,开始以为是memset(sa,0,sizeof(sa))这句少写了但是并不是这样.话说字符串的题特别容易RE.

这道题二分答案然后后缀数组,先将字符串合并,每个串后加一个奇怪的不相同的字符,二分长度,然后在height数组中去找,每次当当前height值小于ans的时候再开一段,这时检查前一段是否符合要求.具体方法先用一个idx[i]表示字符串中第i个属于第几个字符串然后用flag[i]来表示有没有在第i个字符串中出现,最后统计一下flag==1的个数,若>n/2则return true;复杂度更低的O(n*L)正准备学.

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=100*2+10;
const int MAXLEN=10000000*2;
int idx[MAXLEN],n;
struct SuffixArray{
int s[MAXLEN];
int sa[MAXLEN],height[MAXLEN],rank[MAXLEN],n;
int t[MAXLEN*2],t2[MAXLEN*2];
long long cnt[MAXLEN];
SuffixArray(){n=0;}
void clear(){n=0;}
void build_sa(int m){
int i,*x=t,*y=t2;
for(i=0;i<m;i++) cnt[i]=0;
for(i=0;i<n;i++) cnt[x[i]=s[i]]++;
for(i=1;i<m;i++) cnt[i]+=cnt[i-1];
for(i=n-1;i>=0;i--) sa[--cnt[x[i]]]=i;//血的教训,妈蛋这个等号害了我一整天
for(int k=1,p=0;k<n;k <<=1)
{
p=0;
for(i=n-k;i<n;i++) y[p++]=i;
for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
for(i=0;i<m;i++) cnt[i]=0;
for(i=0;i<n;i++) cnt[x[y[i]]]++;
for(i=1;i<m;i++) cnt[i]+=cnt[i-1];
for(i=n-1;i>=0;i--) sa[--cnt[x[y[i]]]]=y[i];
swap(x,y);
p=1;x[sa[0]]=0;
for(i=1;i<n;i++)
if(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k])
x[sa[i]]=p-1;
else x[sa[i]]=p++;
if(p>=n)
break;
m=p;
}
}
void build_height()
{
int k=0;
for(int i=0;i<n;i++) rank[sa[i]]=i;
for(int i=0;i<n;i++)
{
if(k) k--;
if(!rank[i]) continue;
int j=sa[rank[i]-1];
while(s[i+k]==s[j+k]) k++;
height[rank[i]]=k;
}
}
}SA;

inline void add(int ch,int id){
idx[SA.n]=id;
SA.s[SA.n++]=ch;
}

int flag[maxn];
inline int check(int ans){
int check_clock=1;
memset(flag,0,sizeof(flag));
for(int i=1;i<SA.n;i++)
{
if(SA.height[i]>=ans)
{
flag[idx[SA.sa[i]]]=check_clock;
flag[idx[SA.sa[i-1]]]=check_clock;
}
else {
int cnt=0;
for(int j=0;j<n;j++)
if(flag[j]==check_clock) cnt++;
if(cnt>n/2) return true;
flag[idx[SA.sa[i]]]=++check_clock;
}
}
return false;
}

inline void print_ans(int l,int r){
for(int i=l;i<=r;i++)
printf("%c",SA.s[i]+'a'-1);
printf("\n");
}

inline void print(int ans){
int check_clock=1;
memset(flag,0,sizeof(flag));
for(int i=1;i<SA.n;i++)
{
if(SA.height[i]>=ans)
{
flag[idx[SA.sa[i]]]=check_clock;
flag[idx[SA.sa[i-1]]]=check_clock;
}
else {
int cnt=0;
for(int j=0;j<n;j++)
if(flag[j]==check_clock) cnt++;
if(cnt>n/2) print_ans(SA.sa[i-1],SA.sa[i-1]+ans-1);
flag[idx[SA.sa[i]]]=++check_clock;
}
}
}
char s[1000+10];
int kase=0;
int main()
{
int maxlen;
while(scanf("%d",&n)==1&&n)
{
if(kase++) printf("\n");
SA.clear();
maxlen=0;
for(int i=0;i<n;i++){
scanf("%s",s);
int l=strlen(s);
maxlen=max(maxlen,l);
for(int j=0;j<l;j++) add(s[j]-'a'+1,i);
add(100+i,n);
}
if(n==1)
{
printf("%s\n",s);continue;
}
SA.build_sa(101+n);
SA.build_height();
int l=1,r=maxlen,ans=0;
while(l<=r)
{
int mid=((l+r)>>1);
if(check(mid)) ans=mid,l=mid+1;
else r=mid-1;
}
if(ans)print(ans);
else printf("?\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: