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 ...
随机推荐
- 服务器搭建域控与SQL Server的AlwaysOn环境过程(三)配置故障转移
0 引言 主要讲述如何搭建故障转移集群,因为AlwaysOn是基于Windows的故障转移集群的. 在讲解步骤之前需要了解一下故障转移集群仲裁配置 下面图片来自<Windows Server20 ...
- SpringBoot 获取客户端 ip
/** * 获取客户端ip地址 * @param request * @return */ public static String getCliectIp(HttpServletRequest re ...
- [codevs3657]括号序列
题目大意:有一列只有'(',')','[',']'构成的括号序列,求在序列中至少加上多少括号,能使该序列合法. 解题思路:区间dp. 我们以$f[i][j]$表示把区间$[i,j]$添成合法括号所需的 ...
- ActiveMQ服务安装
1.下载安装ActiveMQ服务提供者 http://activemq.apache.org/ 2.启用ActiveMQ服务 cd [activemq_install_dir] bin\activem ...
- MAVEN flex
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...
- 题解 LNOI2014 LCA
题目:传送门 这道题根本不用lca,也没有部分分... 考虑求两个点xy的lca的深度. 我们将x到树根所有点的值都加1,然后查询y到根的和,其实就是lca的深度. 所以本题离线一下上树剖乱搞就可以了 ...
- CAD二次开发(02)-添加对象到模型空间
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- [terry笔记]11gR2_DataGuard搭建_primary零停机
11gR2搭建dataguard环境,此篇文章是利用rman搭建dataguard,这样的好处是primary不用停机,当然,前提条件是primary已经开启归档. 相对于可以停机,零停机传送数据文件 ...
- quick-cocos2d-x游戏开发【2】——项目结构分析、创建新场景
创建完一个新项目之后,我们能够简单的看一看这个项目的文件组成,有这么一个文件层次结构 几个proj.*目录就不用说了,是相应的平台的解决方式,res专门存放我们的游戏资源.scripts存放我们的lu ...
- HDU 1114 Piggy-Bank(一维背包)
题目地址:HDU 1114 把dp[0]初始化为0,其它的初始化为INF.这样就能保证最后的结果一定是满的,即一定是从0慢慢的加上来的. 代码例如以下: #include <algorithm& ...