Poj 3294 Life Forms (后缀数组 + 二分 + Hash)
题目链接:
题目描述:
有n个文本串,问在一半以上的文本串出现过的最长连续子串?
解题思路:
可以把文本串用没有出现过的不同字符连起来,然后求新文本串的height。然后二分答案串的长度K,根据K把新文本串的后缀串分块,统计每块中的原文本串出现的次数,大于原文本串数目的一半就作为答案记录下来,对于输出字典序,height就是排好序的后缀数组,只要按照顺序输出即可。
- #include <cstdio>
- #include <cstring>
- #include <iostream>
- #include <algorithm>
- using namespace std;
- typedef long long LL;
- const int maxn = ;
- int sa[maxn], rank[maxn], height[maxn], vis[], res[maxn];
- int t1[maxn], t2[maxn], r[maxn], flag[maxn], c[maxn];
- bool cmp (int *str, int a, int b, int k)
- {
- return str[a]==str[b] && str[a+k]==str[b+k];
- }
- void da (int *str, int n, int m)
- {
- n ++;
- int *x = t1, *y = t2, i, j;
- for (i=; i<m; i++) c[i] = ;
- for (i=; i<n; i++) c[x[i]=str[i]] ++;
- for (i=; i<m; i++) c[i] += c[i-];
- for (i=n-; i>=; i--) sa[-- c[x[i]]] = i;
- for (j=; j<=n; j*=)
- {
- int p = ;
- for (i=n-j; i<n; i++) y[p++] = i;
- for (i=; i<n; i++) if (sa[i] >= j) y[p++] = sa[i] - j;
- for (i=; i<m; i++) c[i] = ;
- for (i=; i<n; i++) c[x[y[i]]] ++;
- for (i=; i<m; i++) c[i] += c[i-];
- for (i=n-; i>=; i--) sa[-- c[x[y[i]]]] = y[i];
- swap (x, y);
- p = ;
- x[sa[]] = ;
- for (int i=; i<n; i++)//i是rank
- x[sa[i]] = cmp(y, sa[i-], sa[i], j)?p-:p++;
- if (p >= n)
- break;
- m = p;
- }
- for (i=; i<n; i++)
- rank[sa[i]] = i;
- int k = ;
- n --;
- for (int i=; i<n; i++)
- {
- if (k) k --;
- int j = sa[rank[i] - ];
- while (str[i+k] == str[j+k]) k++;
- height[rank[i]] = k;
- }
- }
- bool Bin_sreach (int x, int k, int n)
- {
- int ans, num;
- ans = num = ;
- memset (vis, , sizeof(vis));
- for (int i=; i<=k; i++)
- {
- if (height[i] >= x)
- {
- ans += vis[flag[sa[i-]]]?:;
- vis[flag[sa[i-]]] = ;
- ans += vis[flag[sa[i]]]?:;
- vis[flag[sa[i]]] = ;
- }
- else
- {
- if (ans* > n)
- res[++ num] = sa[i-];
- ans = ;
- memset (vis, , sizeof(vis));
- }
- }
- if (ans* > n)
- res[++ num] = sa[k-];
- if (num)
- {
- res[] = num;
- return true;
- }
- return false;
- }
- int main ()
- {
- int n, l = ;
- char str[];
- while (scanf ("%d", &n), n)
- {
- if (l ++)
- printf ("\n");
- int k = ;
- for (int i=; i<n; i++)
- {
- scanf ("%s", str);
- for (int j=; str[j]; j++)
- {
- r[k] = str[j];
- flag[k++] = i;//记录k字母所在的字符串
- }
- r[k] = + i;
- flag[k++] = -;
- }
- r[k] = ;
- da (r, k, );
- int low = , high = k, mid, ans = ;
- while (low <= high)
- {//二分枚举
- mid = (low + high) / ;
- if (Bin_sreach(mid, k, n))
- {
- ans = mid;
- low = mid + ;
- }
- else
- high = mid - ;
- }
- if (low == )
- {
- printf ("?\n");
- continue;
- }
- for (int i=; i<=res[]; i++)
- {
- for (int j=res[i]; j<res[i]+ans; j ++)
- printf ("%c", r[j]);
- printf ("\n");
- }
- }
- return ;
- }
Poj 3294 Life Forms (后缀数组 + 二分 + Hash)的更多相关文章
- poj 3294 Life Forms - 后缀数组 - 二分答案
题目传送门 传送门I 传送门II 题目大意 给定$n$个串,询问所有出现在严格大于$\frac{n}{2}$个串的最长串.不存在输出'?' 用奇怪的字符把它们连接起来.然后求sa,hei,二分答案,按 ...
- POJ 3294 Life Forms 后缀数组+二分 求至少k个字符串中包含的最长子串
Life Forms Description You may have wondered why most extraterrestrial life forms resemble humans, ...
- Poj 1743 Musical Theme(后缀数组+二分答案)
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 28435 Accepted: 9604 Descri ...
- [poj 1743] Musical Theme 后缀数组 or hash
Musical Theme 题意 给出n个1-88组成的音符,让找出一个最长的连续子序列,满足以下条件: 长度大于5 不重叠的出现两次(这里的出现可以经过变调,即这个序列的每个数字全都加上一个整数x) ...
- Poj 3261 Milk Patterns(后缀数组+二分答案)
Milk Patterns Case Time Limit: 2000MS Description Farmer John has noticed that the quality of milk g ...
- POJ 1226 Substrings(后缀数组+二分答案)
[题目链接] http://poj.org/problem?id=1226 [题目大意] 求在每个给出字符串中出现的最长子串的长度,字符串在出现的时候可以是倒置的. [题解] 我们将每个字符串倒置,用 ...
- BZOJ 4278: [ONTAK2015]Tasowanie (后缀数组 / 二分+hash)
直接归并,然后如果哪边的后缀字典序比较小就去哪边,然后就可以后缀数组 博客传送门- 但是本蒟蒻不会后缀数组 Upd:Upd:Upd:现在会了233.一道差不多的题:BZOJ 1692: [Usaco2 ...
- BZOJ 1692: [Usaco2007 Dec]队列变换 (后缀数组/二分+Hash)
跟BZOJ 4278: [ONTAK2015]Tasowanie一模一样 SA的做法就是把原串倒过来接在原串后面,O(nlogn)O(nlogn)O(nlogn)做后缀数组,就能O(1)O(1)O(1 ...
- POJ3294--Life Forms 后缀数组+二分答案 大于k个字符串的最长公共子串
Life Forms Time Limit: 500 ...
随机推荐
- Building clang on RedHat
http://btorpey.github.io/blog/2015/01/02/building-clang/ clang is a great compiler, with a boatload ...
- kvm虚拟化学习笔记(四)之kvm虚拟机日常管理与配置
KVM虚拟化学习笔记系列文章列表----------------------------------------kvm虚拟化学习笔记(一)之kvm虚拟化环境安装http://koumm.blog.51 ...
- CV_HAAR_FEATURE_DESC_MAX和CV_HAAR_FEATURE_MAX
#define CV_HAAR_FEATURE_MAX 3 //提前定义的一个宏,在程序中表示一个haar特征由至多三个矩形组成 #define CV_HAAR_FEATURE_DESC_MAX 20 ...
- nagios 安装配置(包含nrpe端)全 (三)
四.系统的配置: 1.介绍 在配置过程中涉及到的几个定义有:主机.主机组,服务.服务组.联系人.联系人组,监控时间.监控命令等. 最重要的有四点: 第一:定义监控哪些主机.主机组.服务和服务组: 第二 ...
- Linux(Ubuntu14.04)下Google Chrome / Chromium标题栏乱码问题
注:我使用的Linux发行版是Ubuntu 14.04,不同Linux发行版可能会有不同. 最近在使用Chromium的时候tab的标题栏中文显示乱码,在地址栏输入中文是同样时乱码,就像下图: 看起来 ...
- Java中有多少种设计模式?请简单画一下三种常见设计模式的类图?
转载:http://blog.csdn.net/longyulu/article/details/9159589 一.设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽 ...
- docker启动centos容器后如何用putty连接
在前面的文章中,我提到过,win10 docker启动容器时,只有配置了宿主机和docker容器的端口映射,外部应用才能访问到容器中的服务,比如映射到Nginx的80端口.现在我将宿主机的某个端口映射 ...
- MongoDB相关的一些技术文章
安装 win7下安装和配置MongoDB的总结---阿冬专栏
- 计算机设计思想 —— 代理(proxy)
0. 理解 两个说着不同母语国家的人想要交流通话,各人说着各自的母语显然是无法沟通的,此时需要一个翻译,一个媒介(medium).中介,或者一个代理(proxy),比如通用的国际语言英语,比如全世界人 ...
- 【转】js中15个常用的正则表达式+正则集合
1 用户名正则 //用户名正则,4到16位(字母,数字,下划线,减号) var uPattern = /^[a-zA-Z0-9_-]{4,16}$/; //输出 true console.log(uP ...