POJ3294 Life Forms(后缀数组)
引用罗穗骞论文中的话:
将n 个字符串连起来,中间用不相同的且没有出现在字符串中的字符隔开,求后缀数组。然后二分答案,用和例3 同样的方法将后缀分成若干组,判断每组的后缀是否出现在不小于k 个的原串中。这个做法的时间复杂度为O(nlogn)。
- #include<cstdio>
- #include<iostream>
- #include<algorithm>
- #include<vector>
- #include<cstring>
- #include<cstdlib>
- using namespace std;
- const int N = 110008;
- int wa[N],wb[N],wv[N],ws0[N];
- int val[N], sum[N], tp1[N], tp2[N];
- int sa[N], rank[N], height[N];
- int hs[N];
- char tp[1008];
- int str[N];
- bool vis[1000];
- vector<int> v;
- 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++) ws0[i]=0;
- for(i=0;i<n;i++) ws0[x[i]=r[i]]++;
- for(i=1;i<m;i++) ws0[i]+=ws0[i-1];
- for(i=n-1;i>=0;i--) sa[--ws0[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++) ws0[i]=0;
- for(i=0;i<n;i++) ws0[wv[i]]++;
- for(i=1;i<m;i++) ws0[i]+=ws0[i-1];
- for(i=n-1;i>=0;i--) sa[--ws0[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++;
- }
- return;
- }
- 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++);
- return;
- }
- bool check(int m, int n, int num){
- memset(vis , 0, sizeof(vis));
- int cnt = 0;
- int size = 0;
- for(int i = 1; i <= n ;i++){
- if(height[i] >= m){//分组,同组内计数
- if(!vis[hs[ sa[i] ]]){
- cnt++;
- vis[hs[ sa[i] ]] = 1;
- }
- if(!vis[hs[ sa[i - 1] ]]){//不同组
- cnt++;
- vis[hs[ sa[i - 1] ]] = 1;
- }
- }else{
- if(cnt > num){
- if(size == 0){
- v.clear();
- }
- size++;
- v.push_back(sa[i - 1]);
- }
- cnt = 0;
- memset(vis, 0 , sizeof(vis));
- }
- }
- if(size){
- return true;
- }else{
- return false;
- }
- }
- int main(){
- int k;
- bool flag = 0;
- while(~scanf("%d", &k ) && k){
- v.clear();
- int n = 0;
- int mini = 100000000;
- for(int t = 0; t < k; t++){
- scanf("%s", tp);
- int len = strlen(tp);
- mini = min(mini, len);
- for(int i = n, j = 0; j < len; i++, j++){
- str[i] = tp[j];
- hs[i] = t;
- }
- n += len + 1;
- if(t != k - 1){
- str[n - 1] = t + 130;
- }
- }
- n--;
- str[n] = 0;
- da(str, sa , n + 1 , 256);
- calheight(str, sa, n);
- int l = 1, r = mini;
- int ans = 0;
- while(l <= r){
- int m = (l + r)>>1;
- if(check(m, n, k / 2 )){
- l = m + 1;
- ans = m;
- }else{
- r = m - 1;
- }
- }
- if(flag){
- printf("\n");
- }
- flag = 1;
- if(ans){
- for(int i = 0; i < v.size(); i++){
- int st = v[i];
- for(int j = 0; j < ans; j++){
- printf("%c", str[st + j]);
- }
- printf("\n");
- }
- }else{
- printf("?\n");
- }
- }
- return 0;
- }
POJ3294 Life Forms(后缀数组)的更多相关文章
- POJ3294 Life Forms —— 后缀数组 最长公共子串
题目链接:https://vjudge.net/problem/POJ-3294 Life Forms Time Limit: 5000MS Memory Limit: 65536K Total ...
- UVA11107 Life Forms --- 后缀数组
UVA11107 Life Forms 题目描述: 求出出现在一半以上的字符串内的最长字符串. 数据范围: \(\sum len(string) <= 10^{5}\) 非常坑的题目. 思路非常 ...
- Poj 3294 Life Forms (后缀数组 + 二分 + Hash)
题目链接: Poj 3294 Life Forms 题目描述: 有n个文本串,问在一半以上的文本串出现过的最长连续子串? 解题思路: 可以把文本串用没有出现过的不同字符连起来,然后求新文本串的heig ...
- POJ 3294 UVA 11107 Life Forms 后缀数组
相同的题目,输出格式有区别. 给定n个字符串,求最长的子串,使得它同时出现在一半以上的串中. 不熟悉后缀数组的童鞋建议先去看一看如何用后缀数组计算两个字符串的最长公共子串 Ural1517 这道题的思 ...
- POJ3294--Life Forms 后缀数组+二分答案 大于k个字符串的最长公共子串
Life Forms Time Limit: 500 ...
- POJ 3294 Life Forms 后缀数组+二分 求至少k个字符串中包含的最长子串
Life Forms Description You may have wondered why most extraterrestrial life forms resemble humans, ...
- poj 3294 Life Forms - 后缀数组 - 二分答案
题目传送门 传送门I 传送门II 题目大意 给定$n$个串,询问所有出现在严格大于$\frac{n}{2}$个串的最长串.不存在输出'?' 用奇怪的字符把它们连接起来.然后求sa,hei,二分答案,按 ...
- 2018.11.28 poj3294 Life Forms(后缀数组+双指针)
传送门 后缀数组经典题目. 我们先把所有的字符串都接在一起. 然后求出hththt数组和sasasa数组. 然后对于sasasa数组跑双指针统计答案. 如果双指针包括进去的属于不同字符串的数量达到了题 ...
- POJ3294 Life Forms(二分+后缀数组)
给n个字符串,求最长的多于n/2个字符串的公共子串. 依然是二分判定+height分组. 把这n个字符串连接,中间用不同字符隔开,跑后缀数组计算出height: 二分要求的子串长度,判断是否满足:he ...
随机推荐
- Linux下端口被占用解决
有时候关闭软件后,后台进程死掉,导致端口被占用.下面以JBoss端口8083被占用为例,列出详细解决过程. 解决方法: 1.查找被占用的端口 netstat -tln netstat -tln | ...
- UOJ 做题记录
UOJ 做题记录 其实我这么弱> >根本不会做题呢> > #21. [UR #1]缩进优化 其实想想还是一道非常丝播的题目呢> > 直接对于每个缩进长度统计一遍就好 ...
- trac中wiki直接显示任务代码
= 我的任务 = [[TicketQuery(max=10,owner=$USER, status!=closed|verified|cancelled, order=id,desc=1,format ...
- Silverlight 中datagrid控件-- 通过设置数据虚拟化加速显示
定义依赖属性作为datagrid的数据源 protected static readonly DependencyProperty ViewLogsProperty = DependencyPrope ...
- Python之多线程
廖雪峰教程--- http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/00138683 ...
- centos6.5 nginx开机启动
/etc/init.d/下添加nginxd文件,内容如下: #!/bin/bash # #chkconfig: - #description: Nginx is a World Wide Web se ...
- libreoffice安装
centos7下libreoffice的安装 #下载安装包wget http://mirrors.ustc.edu.cn/tdf/libreoffice/stable/5.1.1/rpm/x86_64 ...
- ACM/ICPC 之 最短路-Floyd+SPFA(BFS)+DP(ZOJ1232)
这是一道非常好的题目,融合了很多知识点. ZOJ1232-Adventrue of Super Mario 这一题折磨我挺长时间的,不过最后做出来非常开心啊,哇咔咔咔 题意就不累述了,注释有写,难点在 ...
- 2106 Problem F Shuffling Along 中石油-未提交-->已提交
题目描述 Most of you have played card games (and if you haven’t, why not???) in which the deck of cards ...
- javascript 中 filter 方法
filter 方法用来迭代一个数组,并且按给出的条件过滤出符合的元素. filter 方法传入一个回调函数,这个回调函数会携带一个参数,参数为当前迭代的项(我们叫它 val ). 回调函数返回 tru ...