POJ 1724 Corporate Identity 后缀数组
来源:互联网 发布:阴茎上白色米粒知乎 编辑:程序博客网 时间:2024/06/05 14:11
题意:给出N个字符串,求出最长且字典序最小的子串,满足在每个字符串中出现。
思路:同样是二分答案,对height数组进行分组。从前向后扫的过程中,找到第一个满足题意的子串就是字典序最小的。
代码如下:
#include <cstring>#include <cstdio>#include <algorithm>#include <set>using namespace std; static const int maxn =1000100; int rk[maxn],sa[maxn],height[maxn]; int a[maxn],b[maxn],cont[200000]; //待排序字符串为r,长度为n,范围r[0] - r[n-1],值额范围0 - n-1. //字符集为m,范围1 - m; void radix_sort(int * r, int *a, int *b, int n, int m){//将a按照r进行基数排序,储存到b,长度为n,字符集为m memset(cont,0,sizeof(cont)); for(int i = 0; i < n; ++i) ++cont[r[a[i]]]; for(int i = 1; i <= m; ++i) cont[i] += cont[i-1]; for(int i = n -1; i >= 0; --i) b[--cont[r[a[i]]]] = a[i]; } void calc_sa(int*r, int n, int m){ for(int i = 0; i < n; ++i) rk[i] =i; radix_sort(r,rk,sa,n,m); rk[sa[0]] = 0; for(int i = 1; i < n; ++i) rk[sa[i]]= rk[sa[i-1]] +(r[sa[i]]!=r[sa[i-1]]); for(int i = 0; 1<<i< n; ++i){ for(int j = 0; j < n; ++j){ a[j] = rk[j]+1; b[j] = j + (1<<i) >=n? 0: rk[j + (1<<i)] + 1; sa[j] = j; } radix_sort(b,sa,rk,n,n); radix_sort(a,rk,sa,n,n); rk[sa[0]] = 0; for(int j = 1; j < n; ++j){ rk[sa[j]] = rk[sa[j-1]] + (a[sa[j-1]] != a[sa[j]] || b[sa[j-1]] != b[sa[j]]); } } } void calc_height(int * r,int n) {//计算height for(int i = 0 ; i < n; ++i) rk[sa[i]] = i; int h = 0; for(int i = 0; i < n; ++i){ h = h == 0?0: h - 1; if(rk[i]!= 0) while(r[i + h] == r[sa[rk[i]-1] + h]) h++; height[rk[i]] = h; } }int r[1000010];char str[10010];int n,N,pos,len;bool vis[4010];bool judge(int mid){ int cnt = 0; for(int i = 0; i < n; ++i){ if(height[i] < mid){ memset(vis,0,sizeof(vis)); cnt = 0; continue; } int l1 = sa[i] / (len+1), l2 = sa[i-1] / (len+1); if(!vis[l1]) vis[l1] = true, cnt++; if(!vis[l2]) vis[l2] = true, cnt++; if(cnt == N){ pos = sa[i]; return true; } } return false;}int main(void){ ///freopen("input.txt","r",stdin); //freopen("out.txt","w",stdout); while(scanf("%d",&N),N){ n = 0; for(int i = 0; i < N; ++i){ scanf("%s",str); for(int j = 0; str[j];++j) r[n++] = str[j]; r[n++] = 1000+i; } len = strlen(str); calc_sa(r,n,6000); calc_height(r,n); int lb = 0, ub = len + 1; while(lb + 1 < ub){ int mid = (lb + ub) >> 1; if(judge(mid)) lb = mid; else ub = mid; } //printf("%d\n",lb); if(lb == 0) puts("IDENTITY LOST"); else{ for(int i = 0; i < lb; ++i) putchar(r[pos+i]); putchar('\n'); } } return 0;}
0 0
- POJ 1724 Corporate Identity 后缀数组
- 【后缀数组】 POJ 3450 Corporate Identity
- POJ3450:Corporate Identity(后缀数组)
- POJ3450 Corporate Identity 【后缀数组】
- poj 3450 Corporate Identity(后缀数组+二分)
- POJ 3450 Corporate Identity(后缀数组+二分)
- POJ-3450 Corporate Identity(KMP/后缀数组)
- HDU 2328 Corporate Identity 后缀数组
- hdu 2328 Corporate Identity (后缀数组应用)
- |hdu 2328|后缀数组|二分|Corporate Identity
- poj3450 Corporate Identity kmp || 后缀数组
- POJ 3450--->Corporate Identity(后缀数组求多个字符串的公共子串)
- poj 3450 Corporate Identity(后缀数组 多个字符串的最长公共字串)
- hdu2328——Corporate Identity(后缀数组练习)
- poj3450 Corporate Identity(后缀数组+二分答案)
- poj 3450 Corporate Identity
- POJ-3450-Corporate Identity
- POJ 3450 Corporate Identity
- SDL2源代码分析7:显示(SDL_RenderPresent())
- Android Studio如何选择查看指定进程的log?
- iOS中的状态栏
- SVN中“分支/标记”和“合并”的用法
- java.security.MessageDigest
- POJ 1724 Corporate Identity 后缀数组
- 解决Xming字体太小的问题
- 对以后有点想法了
- STM32 SD bootloader实现
- hdu 5009 dp+离散化
- JAVA笔试题
- KNN算法图解(MATLAB实例)
- linux awk
- 博客的开始