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



题意:
要求全部正向或者反向出如今超过k/2个串中的子串

思路:
还是和曾经一样二分答案。使用二进制来标记状态

#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(后缀数组)的更多相关文章

  1. 后缀数组的倍增算法(Prefix Doubling)

    后缀数组的倍增算法(Prefix Doubling) 文本内容除特殊注明外,均在知识共享署名-非商业性使用-相同方式共享 3.0协议下提供,附加条款亦可能应用. 最近在自学习BWT算法(Burrows ...

  2. BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]

    4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...

  3. BZOJ 1692: [Usaco2007 Dec]队列变换 [后缀数组 贪心]

    1692: [Usaco2007 Dec]队列变换 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1383  Solved: 582[Submit][St ...

  4. POJ3693 Maximum repetition substring [后缀数组 ST表]

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9458   Acc ...

  5. POJ1743 Musical Theme [后缀数组]

    Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 27539   Accepted: 9290 De ...

  6. 后缀数组(suffix array)详解

    写在前面 在字符串处理当中,后缀树和后缀数组都是非常有力的工具. 其中后缀树大家了解得比较多,关于后缀数组则很少见于国内的资料. 其实后缀数组是后缀树的一个非常精巧的替代品,它比后缀树容易编程实现, ...

  7. 【UOJ #35】后缀排序 后缀数组模板

    http://uoj.ac/problem/35 以前做后缀数组的题直接粘模板...现在重新写一下模板 注意用来基数排序的数组一定要开到N. #include<cstdio> #inclu ...

  8. 【BZOJ-2119】股市的预测 后缀数组

    2119: 股市的预测 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 334  Solved: 154[Submit][Status][Discuss ...

  9. 【BZOJ-4698】Sandy的卡片 后缀数组

    4698: Sdoi2008 Sandy的卡片 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 140  Solved: 55[Submit][Stat ...

随机推荐

  1. CDR X6三折促销活动,可入

    继CDR X6双十二限量活动之后,CorelDRAW官方为庆祝2018新年新气象,折扣狂潮,又来一波.上次活动由于时间短,任务急,数量少,使得不少小伙伴抱憾而止,选择默默等待良机.现在,良机来了,即便 ...

  2. 联想E490 加M.2固态硬盘 卡在第一画面不动解决办法

    电脑配置:  E490  500G机械硬盘,自己加M.2 NVMe 固态硬盘. 问题:启动时出现 2101:Detection error on SSD1(M.2),  无法识别到机械硬盘 (重新插拨 ...

  3. 一片非常有趣的文章 三分钟读懂TT猫分布式、微服务和集群之路

    原文http://www.cnblogs.com/smallSevens/p/7501932.html#3782600 三分钟读懂TT猫分布式.微服务和集群之路   针对新手入门的普及,有过大型网站技 ...

  4. 关于vue事件监听的一个问题

    由于新工作需要用vue,所以最近接触最多的也是vue,因为之前一直在用react,所以对于vue上手还是很快的.我也尽量找一些他们两个的异同点,除了多了一些辅助用的方法以外,最大的不同应该是对于组件间 ...

  5. C#打开或者创建一个文件,然后向其末尾写入数据的方法

    原文:C#打开或者创建一个文件,然后向其末尾写入数据的方法             FileStream fs = new FileStream(@"d:\timetick.txt" ...

  6. 【codeforces 816A】Karen and Morning

    [题目链接]:http://codeforces.com/contest/816/problem/A [题意] 让你一分钟一分钟地累加时间; 问多长时间以后是个回文串; [题解] reverse之后如 ...

  7. Objective-C的陷阱与缺陷

    Objective-C是一个强大而且非常有用的语言,但是同样也是有一点危险的.这次主题是受到一篇有关C++陷阱的文章启发,来聊聊Objective-C和Cocoa中的陷阱. 简介 我将和Horstma ...

  8. mysql-组合查询

    一.组合查询 mysql允许执行多个查询(多条select语句),并将结果作为单个查询结果集返回.这些组合查询通常称为并(union)或复合查询(compound query). 有两种情况需要使用组 ...

  9. nginx模块开发

    开发方法參考淘宝的教程 这个模块的功能是向client发送一个文件,类似于网页上的另存为功能 #include <ngx_config.h> #include <ngx_core.h ...

  10. Configuration file schema for the .NET Framework

    https://docs.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/index Runtime Settings ...