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 ...
随机推荐
- 模板层 Template
每一个 Web 框架都需要一种很便利的方法用于动态生成 HTML 页面. 最常见的做法是使用模板. 模板包含所需 HTML 页面的静态部分,以及一些特殊的模版语法,用于将动态内容插入静态部分. 说白了 ...
- The Node.js Event Loop, Timers, and process.nextTick() Node.js事件循环,定时器和process.nextTick()
个人翻译 原文:https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/ The Node.js Event Loop, Ti ...
- (noip模拟十七)【BZOJ3930】[CQOI2015]选数-容斥水法
Description 我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案.小z很好奇这样选出的数的最大公约数的规律,他决定对每种方案选出的N个整数都求一次最大公 ...
- 有趣的console
博文第一篇,就以前端调试的“座上客”---console开始
- Java基础学习总结(8)——super关键字
一.super关键字 在JAVA类中使用super来引用父类的成分,用this来引用当前对象,如果一个类从另外一个类继承,我们new这个子类的实例对象的时候,这个子类对象里面会有一个父类对象.怎么去引 ...
- NYIST 46 最少乘法次数
最少乘法次数 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 给你一个非零整数,让你求这个数的n次方,每次相乘的结果可以在后面使用,求至少需要多少次乘.如24:2*2 ...
- Linux 环境下/etc/profile和/etc/profile.d 的区别
Linux 环境下/etc/profile和/etc/profile.d 的区别 区别: 1. 两个文件都是设置环境变量文件的,/etc/profile是永久性的环境变量,是全局变量,/etc/pro ...
- Qt之自定义布局管理器(QBorderLayout)
简述 QBorderLayout,顾名思义-边框布局,实现了排列子控件包围中央区域的布局. 具体实现要求不再赘述,请参考前几节内容. 简述 实现 效果 源码 使用 实现 QBorderLayout主要 ...
- 【iOS开发-47】怎样下载iOS 7.1 Simulator 以及iOS 8离线的Documentation这些文件?
(1)最官方的解决的方法 在Xcode6里面提供下载. 依照下图找到下载就可以. 一般建议把以下的自己主动检查更新和下载的框框勾起来,这样它会帮我们自己主动下载. watermark/2/text/a ...
- BZOJ 4448 主席树+树链剖分(在线)
为什么题解都是离线的-- (抄都没法抄) 搞一棵主席树 1 操作 新树上的当前节点设成1 2 操作 查max(i-xx-1,0)那棵树上这条路径上有多少个点是1 让你找经过了多少个点 查的时候用dee ...