CSU1608: Particle Collider(后缀数组)
Description
In the deep universe, there is a beautiful planet named as CS on which scientists have decided to build Immense Colossal Particle Collider (i.e. ICPC) to find the ultimate theory of the universe. The ICPC is made up with several fragments, and each fragment
has a series of energy level. Any continuous sub-series of energy level corresponds to one type of microscopic particle and can accelerate it with a remarkable effect. Scientists have found that the observation of the certain type of particle is remarkable
enough if its corresponding energy level sub-series appears in more than one half fragments. Another thing, the reverse of one specific sub-series of energy level corresponds to the antiparticle of the particle corresponded by its original sub-series. As we
all know, when a particle meets its antiparticle, DUANG DUANG, a very remarkable phenomenon can be observed by scientists. For simplicity, scientists have declared that it is not remarkable enough until the total count of the appearance in the different fragments
of the original sub-series and its reverse is more than one half the number of fragments. Lastly, both in the first and the second condition, the longer the sub-series is, the more remarkable observation can be get.
Well, so long a paragraph, science is really complicated. Now, questions come: given a set of fragments with a series of energy level, find the sub-series which can get the most remarkable observation.
Input
There are several cases. Every case comes a line with a positive integer N (N <= 10) first of all, followed by N lines each of which contains a nonempty series of capital letters representing energy levels. All series have a length not more than 1000.
Output
For every case, output the wanted sub-series. If there are more than one, output them in the alphabetical order, each in one line. If there is none, output NONE. Note that whenever one sub-series and its reverse appear simultaneously with the satisfied condition,
it is available to output only the less one in alphabetical order of them two even if any of them two appears more than one half N times.
Sample Input
3
ABC
ABD
BCD
3
AAA
BBB
CCC
2
ABC
DBA
Sample Output
AB
BC
NONE
AB
HINT
Source
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <math.h>
#include <bitset>
#include <algorithm>
#include <climits>
using namespace std; #define LS 2*i
#define RS 2*i+1
#define UP(i,x,y) for(i=x;i<=y;i++)
#define DOWN(i,x,y) for(i=x;i>=y;i--)
#define MEM(a,x) memset(a,x,sizeof(a))
#define W(a) while(a)
#define gcd(a,b) __gcd(a,b)
#define LL long long
#define N 1000005
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define EXP 1e-8
int wa[N],wb[N],wsf[N],wv[N],sa[N];
int rank1[N],height[N],s[N],a[N];
//sa:字典序中排第i位的起始位置在str中第sa[i]
//rank:就是str第i个位置的后缀是在字典序排第几
//height:字典序排i和i-1的后缀的最长公共前缀
int cmp(int *r,int a,int b,int k)
{
return r[a]==r[b]&&r[a+k]==r[b+k];
}
void getsa(int *r,int *sa,int n,int m)//n要包括末尾加入的0
{
int i,j,p,*x=wa,*y=wb,*t;
for(i=0; i<m; i++) wsf[i]=0;
for(i=0; i<n; i++) wsf[x[i]=r[i]]++;
for(i=1; i<m; i++) wsf[i]+=wsf[i-1];
for(i=n-1; i>=0; i--) sa[--wsf[x[i]]]=i;
p=1;
j=1;
for(; 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++) wsf[i]=0;
for(i=0; i<n; i++) wsf[wv[i]]++;
for(i=1; i<m; i++) wsf[i]+=wsf[i-1];
for(i=n-1; i>=0; i--) sa[--wsf[wv[i]]]=y[i];
t=x;
x=y;
y=t;
x[sa[0]]=0;
for(p=1,i=1; i<n; i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)? p-1:p++;
}
}
void getheight(int *r,int n)//n不保存最后的0
{
int i,j,k=0;
for(i=1; i<=n; i++) rank1[sa[i]]=i;
for(i=0; i<n; i++)
{
if(k)
k--;
else
k=0;
j=sa[rank1[i]-1];
while(r[i+k]==r[j+k])
k++;
height[rank1[i]]=k;
}
} char str[N];
int id[N];
map<string,int> mat,ans;
map<string,int>::iterator it; int check(int x)//统计该状态包括几个串
{
int i,cnt = 0;
for(i = 1; i<=10; i++)
if((1<<i)&x)
cnt++;
return cnt;
} int main()
{
int n,i,j,k,len;
while(~scanf("%d",&k))
{
MEM(id,0);
n = 0;
int p = 200;
for(i = 1; i<=k; i++)
{
scanf("%s",str);
len = strlen(str);
for(j = 0; j<len; j++)
{
id[n] = i;
s[n++] = str[j];
}
s[n++] = p++;
for(j = len-1; j>=0; j--)
s[n++] = str[j];
s[n++] = p++;
}
if(k == 1)
{
printf("%s\n",str);
continue;
}
getsa(s,sa,n,p);
getheight(s,n);
int l = 1,r = 1000;
ans.clear();
while(l<=r)
{
int mid = (l+r)/2;
i = 0;
mat.clear();
while(i<n)
{
if(height[i]>=mid)
{
int tem = 1<<id[sa[i-1]];
len = 2000;
while(height[i]>=mid && i<n)//二进制记录串
{
tem |= (1<<id[sa[i]]);
len = min(len,height[i]);
i++;
}
if(tem!=1)
{
char s1[1005],s2[1005];
for(j = len-1; j>=0; j--)
{
s1[len-1-j] = s[sa[i-1]+j];
s2[j] = s[sa[i-1]+j];
}
s1[len] = s2[len] = '\0';
if(mat.find(string(s1)) != mat.end())
mat[string(s1)] |= tem;
else
mat[string(s2)] = tem;
}
}
i++;
}
int flag = 0;
for(it = mat.begin(); it!=mat.end(); it++)
{
if(check(it->second) >= k/2+1)
{
if(flag==0)
{
ans.clear();
flag = 1;
}
ans.insert(*it);
}
}
if(flag==0) r = mid-1;
else l = mid+1;
}
if(ans.size()==0)
printf("NONE\n");
else
{
for(it = ans.begin(); it!=ans.end(); it++)
{
printf("%s\n",it->first.c_str());
}
}
} return 0;
}
CSU1608: Particle Collider(后缀数组)的更多相关文章
- 后缀数组的倍增算法(Prefix Doubling)
后缀数组的倍增算法(Prefix Doubling) 文本内容除特殊注明外,均在知识共享署名-非商业性使用-相同方式共享 3.0协议下提供,附加条款亦可能应用. 最近在自学习BWT算法(Burrows ...
- BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]
4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...
- BZOJ 1692: [Usaco2007 Dec]队列变换 [后缀数组 贪心]
1692: [Usaco2007 Dec]队列变换 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1383 Solved: 582[Submit][St ...
- POJ3693 Maximum repetition substring [后缀数组 ST表]
Maximum repetition substring Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9458 Acc ...
- POJ1743 Musical Theme [后缀数组]
Musical Theme Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 27539 Accepted: 9290 De ...
- 后缀数组(suffix array)详解
写在前面 在字符串处理当中,后缀树和后缀数组都是非常有力的工具. 其中后缀树大家了解得比较多,关于后缀数组则很少见于国内的资料. 其实后缀数组是后缀树的一个非常精巧的替代品,它比后缀树容易编程实现, ...
- 【UOJ #35】后缀排序 后缀数组模板
http://uoj.ac/problem/35 以前做后缀数组的题直接粘模板...现在重新写一下模板 注意用来基数排序的数组一定要开到N. #include<cstdio> #inclu ...
- 【BZOJ-2119】股市的预测 后缀数组
2119: 股市的预测 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 334 Solved: 154[Submit][Status][Discuss ...
- 【BZOJ-4698】Sandy的卡片 后缀数组
4698: Sdoi2008 Sandy的卡片 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 140 Solved: 55[Submit][Stat ...
随机推荐
- EasyUI Combotree只选择叶子节点
EasyUI Combotree的方法拓展自Combo和Tree.而Tree有一个onBeforSelect事件来帮助我们实现只选择叶子节点的功能. Tree事件需要 'node' 参数,它包括下列属 ...
- [codevs3657]括号序列
题目大意:有一列只有'(',')','[',']'构成的括号序列,求在序列中至少加上多少括号,能使该序列合法. 解题思路:区间dp. 我们以$f[i][j]$表示把区间$[i,j]$添成合法括号所需的 ...
- OC中的@的作用研究
OC中的@字符用的频率很的高,其主要作用是为了差别于其它语言的keyword和语法 以下我们来研究一下其应用 1.声明类,协议,延展,权限,属性等 @interface声明类 @protocol声明协 ...
- mysql-用正则表达式进行搜索
正则表达式的作用是匹配文本,将一个模式(正则表达式)与一个文本串进行比较,mysql允许你指定正则表达式,过滤select检索出的数据.但是mysql仅仅支持正则表达式的一个子集. 1.基本字符匹配: ...
- sas数据导入终极汇总-之中的一个
将数据文件读入SAS --DATA Step / PROC IMPORT 1.将SAS文件读入SAS-- data sasuser.saslin; set "F:\sa ...
- MyEclipse完好提示配置
MyEclipse完好提示配置 一般的,MyEclipse中的提示以"."后进行提示,不是非常完好.如今.改动提示配置,让提示更完好. 详细操作例如以下: 1.打开MyEclips ...
- Redis 存储图片 [base64/url/path]vs[object]
一.base64图片编解码 基本流程:从网络获取下载一张图片.然后base64编码,再base64解码,存到本地E盘根文件夹下. import java.awt.image.BufferedImage ...
- blog_html
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE html> <html b:v ...
- hdoj--1005--Number Sequence(规律题)
Number Sequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- Mvc 返回文件直接下载
今天碰到一个问题,前端点击下载文件,后端判断文件是否存在,不存在则自动生成文件(图片),返回前端会自动下载文件 网上查了一些 Mvc action中返回File类型 设置一些contentType ...