POJ 3080 Blue Jeans
2015-12-08 17:52
302 查看
作为后缀数组的练习题,更好地理解后缀数组的用法,来写了这道题,应该是比life forms那道题更简单一点,整个程序结构和那道题几乎是一模一样的,这次更好地理解了check函数里面一些细节,比如记录位置变量i经常会在循环里面++了一次,下面在进行处理的时候就要人为地-1,这道题还是挺简单的,对后缀数组的用法又加深了印象。
#include <stdlib.h> #include <cstdio> #include <memory.h> using namespace std; #define maxn 1000 #define maxc 15 #define maxl 100 char DNA[maxc][maxl]={0}; int sa[maxn]={0}, height[maxn]={0}, rank[maxn]={0}; int wa[maxn]={0}, wb[maxn]={0}, ws[maxn]={0}, wv[maxn]={0}; int link[maxn]={0}; int st_en[maxc][2]; int cmp(int *r, int a, int b, int l){ return (r[a] == r[b]) && (r[a + l] == r[b + l]); } //计算后缀数组的模板 void DA(int *r, int *sa, int n, int m) { int i, j, p, *x = wa, *y = wb, *t; for (i = 0; i<m; i++) ws[i] = 0; for (i = 0; i<n; i++) ws[x[i] = r[i]]++; for (i = 1; i<m; i++) ws[i] += ws[i - 1]; for (i = n - 1; i >= 0; i--) sa[--ws[x[i]]] = i; for (j = 1, p = 1; p<n; j *= 2, m = p){ for (p = 0, i = n - j; i<n; i++) y[p++] = i; for (i = 0; i<n; i++) if (sa[i] >= j) y[p++] = sa[i] - j; for (i = 0; i<n; i++) wv[i] = x[y[i]]; for (i = 0; i<m; i++) ws[i] = 0; for (i = 0; i<n; i++) ws[wv[i]]++; for (i = 1; i<m; i++) ws[i] += ws[i - 1]; for (i = n - 1; i >= 0; i--) sa[--ws[wv[i]]] = y[i]; for (t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i<n; i++) x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++; } } //计算height数组模板 void calheight(int *r, int *sa, int n) { int i, j, k = 0; for (i = 1; i <= n; i++) rank[sa[i]] = i; for (i = 0; i<n; height[rank[i++]] = k) for (k ? k-- : 0, j = sa[rank[i] - 1]; r[i + k] == r[j + k]; k++); } int ID(int k, int n){ for(int i=0;i<n;++i){ if(k<=st_en[i][1]&&k>=st_en[i][0]) return i; } return -1; } bool check(int k,int n,int tcount,bool output = false){ int i=0; int cnt = 0; while(true){ bool visited[maxn]={0}; while(i<tcount&&height[i]<k) ++i; if(i>=tcount) break; visited[ID(sa[i-1],n)] = 1; cnt = 1; while(i<tcount&&height[i]>=k){ if(!visited[ID(sa[i],n)]){ visited[ID(sa[i],n)] = true; cnt++; } ++i; } if(cnt>=n){ if(output){ for(int j=sa[i-1];j<k+sa[i-1];++j){ printf("%c",link[j]); } printf("\n"); } return true; } } return false; } int main(){ int t; scanf("%d",&t); while(t--){ memset(sa,0,sizeof(sa)); memset(height,0,sizeof(height)); memset(DNA,0,sizeof(DNA)); memset(rank,0,sizeof(rank)); int n; scanf("%d",&n); 4000 for(int i=0;i<n;++i){ scanf("%s",DNA[i]); } int tcount = 0; for(int i=0;i<n;++i){ st_en[i][0] = tcount; for(int j=0;j<60;++j){ link[tcount++] = (int)DNA[i][j]; } st_en[i][1] = tcount; link[tcount++] = i; } DA(link,sa,tcount,200); calheight(link,sa,tcount-1); //printf("tcount: %d\n",tcount); int left = 0, right = 60; while(left<right){ int mid = (left + right + 1)>>1; if(check(mid,n,tcount)) left = mid; else right = mid - 1; } //printf("left: %d\n",left); if(left<3){ printf("no significant commonalities\n"); } else{ check(left,n,tcount,true); } } //system("pause"); return 0; }
相关文章推荐
- 学习 easyui 之一:easyloader 分析与使用
- UI第十九天:数据库
- pcduino nfs挂在光盘
- UItextView,UIscrollView,UITableViewCell三种能够使页面滑动控件的总结(1)
- easyui layout 左右面板折叠后 显示标题
- SunCertPathBuilderException: unable to find valid certification path to requested target
- ecshop后台编辑器替换成ueditor编辑器
- UITableView普通的样式
- j2ee四大作用域pagecontext,request,session,ServletContext
- 如何更好地限制一个UITextField的输入长度
- JUinte测试
- UItableView的性能优化
- IOS之UITextField 禁止粘贴
- 一个简单的Web UI自动化测试框架Java实现
- AlertDialog.Builder的使用
- 杭电 OJ1005Number Sequence(循环节)
- Codeforces 374D Inna and Sequence 二分法+树状数组
- Android 5.0 源码分析 Handler Looper MessageQueue 底层原理
- 完成用户列表Demo,使用plist当数据源,在TableView中显示plist的内容
- iOS UIControl 事件的说明(转)