hdu2328——Corporate Identity(后缀数组练习)
2015-06-25 18:56
357 查看
今天继续后缀数组的练习,在做一道题时花了较多的时间,主要是一些细节上的问题,也是后缀数组题目常出现的一些细节问题,做完这题让我对后缀数组的使用更加熟悉了。
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2328
相关细节在代码中体现:
今天做这题时,就是在一些地方到底要不要用sa数组上纠结了半天。
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2328
相关细节在代码中体现:
//sa存的是排好序的后缀序号,Rank存的是每个后缀序号对应的排名 //用后缀数组时,一定要注意每个数组存的内容,比如说Map存的是每个后缀序号对应的串序号,如果你 //获得了一个后缀序号的排名i,想知道这个后缀序号对应的串序号时,就应该先通过sa[i]获得后缀序号 //在放入到Map数组中获得其对应的串序号。举这个例子就是为了说明做这种题目一定要注意区分后缀序号 //和后缀序号的排名,别搞混了 #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int MAXN=900000; int str[MAXN],sa[MAXN],height[MAXN],a[MAXN],b[MAXN],c[MAXN],Rank[MAXN]; char temp[205],ansStr[205]; bool flag[4005]; int Map[MAXN],index; int n; void char2int(char *s,int *top,int n,int *Min) { int len=strlen(s); if((*Min)>len) (*Min)=len; for(int i=0;i<len;i++) { Map[(*top)]=n;//Map存的是后缀序号对应的串序号 str[(*top)++]=(int)s[i]+1; } } void DA(int top,int m) { int *x=a,*y=b; for(int i=0;i<m;i++) c[i]=0; for(int i=0;i<top;i++) c[x[i]=str[i]]++; for(int i=1;i<m;i++) c[i]+=c[i-1]; for(int i=top-1;i>=0;i--) sa[--c[x[i]]]=i; for(int k=1;k<=top;k*=2) { int p=0; for(int i=top-k;i<top;i++) y[p++]=i; for(int i=0;i<top;i++) if(sa[i]>=k) y[p++]=sa[i]-k; for(int i=0;i<m;i++) c[i]=0; for(int i=0;i<top;i++) c[x[y[i]]]++; for(int i=1;i<m;i++) c[i]+=c[i-1]; for(int i=top-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1; x[sa[0]]=0; for(int i=1;i<top;i++) x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?p-1:p++; if(p>=top) break; m=p; } } void getHeight(int top) { for(int i=1;i<=top;i++)//Rank数组最好在此函数中更新 Rank[sa[i]]=i; int t=0; for(int i=0;i<top;i++) { if(t>0) t--; int j=sa[Rank[i]-1]; while(str[i+t]==str[j+t]) t++; height[Rank[i]]=t;//height存的是后缀序号排名对应的lcp } } bool check() { for(int i=0;i<n;i++) if(flag[i]==false) return false; return true; } bool isOk(int k,int top) { int temp; memset(flag,false,sizeof(flag)); for(int i=1;i<=top;i++) { if(height[i]>=k) { flag[Map[sa[i]]]=true;//得到的i是排名值,而Map需要的是后缀序号,所以要用sa[i]转换 temp=sa[i];//temp使用来求起始下标的,也就是后缀序号,所以也要用sa[i] } else { if(check()) { index=temp; return true; } else { memset(flag,false,sizeof(flag)); flag[Map[sa[i]]]=true; } } } return false; } void getAns(int k) { int top=0; for(int i=index;i<index+k;i++)//获得子串 ansStr[top++]=str[i]-1; ansStr[top]='\0'; } int main() { while(1) { scanf("%d",&n); if(!n) break; int top=0,Min=250; for(int i=0;i<n;i++) { scanf("%s",temp); char2int(temp,&top,i,&Min); if(i!=n-1) { Map[top]=4002; str[top++]=150+i; } } str[top]=0; DA(top+1,150+n); getHeight(top); int ans=0; for(int i=1;i<=Min;i++) { if(isOk(i,top)) ans=i; else break; } if(ans>0) { getAns(ans); printf("%s\n",ansStr); } else printf("IDENTITY LOST\n"); } return 0; }
今天做这题时,就是在一些地方到底要不要用sa数组上纠结了半天。
相关文章推荐
- js 知识备忘
- DOM解析器(七)
- LintCode-最长公共前缀
- MFC SQlite3封装工程
- 海口:男子趁台风天盗窃被抓 新婚妻子方知丈夫是逃犯
- Unable to execute dex: Multiple dex files define Lcom/kenai/jbosh/AbstractAttr
- Git常用命令
- 内存泄露检测工具介绍——leakcanary
- Android应用自动更新功能的代码实现
- wpf 父控件透明子控件不透明
- Codis集群部署测试
- hdu 4324 Triangle LOVE (targan判连通)
- 网络爬虫2--PHP/CURL库(client URL Request Library)
- Python——条件分支
- 性能测试之一----I/O读写速度(2)
- (译)Getting Started——1.3.3 Working with Foundation(使用Foundation框架)
- linux 添加、删除硬盘 mount/unmount
- 卸载oracle 11g数据库软件
- 从 IHTMLDocument2 获得/写入 HTML 文本 (IPersistStreamInit)
- Swift字典