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 ...
随机推荐
- IOCP实现的任务队列
unit IOCPQueue; interface uses windows, classes; type TOnQueueProc = procedure(sender: tobject; Para ...
- C# DataGridView,右键单击RowHeader时显示右键菜单怎么做?
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e) { ...
- C# 9.0新特性
CandidateFeaturesForCSharp9 看到标题,是不是认为我把标题写错了?是的,C# 8.0还未正式发布,在官网它的最新版本还是Preview 5,通往C#9的漫长道路却已经开始.前 ...
- GAN Generative Adversarial Network 生成式对抗网络-相关内容
参考: https://baijiahao.baidu.com/s?id=1568663805038898&wfr=spider&for=pc Generative Adversari ...
- VC++ VS2010 error LNK1123 转换到 COFF 期间失败 怎么办
1 无法输出Hello world 2 点击项目-属性,打开属性页 3 配置属性-清单工具-输入和输出-嵌入清单改成否 4 找出计算机中的所有cvtres.exe,删掉早期的,只留最新版的 ...
- 微信小程序之 ShoppingCart(购物车)
1.项目目录 2.逻辑层 group.js // pages/group/group.js Page({ /** * 页面的初始数据 */ data: { goodslist: [ { id: &qu ...
- map集合排序
默认情况下,HashMap.HashTable.TreeMap.LinkedHashMap的排列顺序比较: package com.per.sdg.demo; import java.util.Has ...
- 视频录制软件&远程支持软件
视频录制软件 软件名:SCREEN2SWF 录制完成后,可以剪辑: 工程文件,需要保存为svp文件:将视频文件保存为.exe self play 文件,或者.swf flash 文件. 远程支持,远程 ...
- java中 ++前后差别试题及静态变量一旦赋值不可改变
package javaTest; public class Increment { private static int k=0; public static void main(String[] ...
- Xcode The identity used to sign the executable is no longer valid. 错误解决
Xcode真机调试时出现问题:Xcode The identity used to sign the executable is no longer valid. Please verify that ...