CSU1608: Particle Collider(后缀数组)

来源:互联网 发布:java注释规范 编辑:程序博客网 时间:2024/05/20 10:14

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

3ABCABDBCD3AAABBBCCC2ABCDBA

Sample Output

ABBCNONEAB

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-8int 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;}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 刚出生的小牛不吃奶怎么办 吃奶的狗崽拉稀怎么办 新生儿吃奶老是呛到怎么办 刚生小狗不吃奶怎么办 刚出生的小羊不吃奶怎么办 羔羊走路不稳不吃奶怎么办 新生儿喝奶老是呛到怎么办 宝宝吃母乳呛到怎么办 宝宝一直睡觉不吃奶怎么办 3个月婴儿不吃奶怎么办 新生婴儿晚上不睡觉怎么办 宝宝肚子胀不吃奶怎么办 宝宝25天不睡觉怎么办 50天婴儿不吃奶怎么办 儿子关在房间玩电脑怎么办? 宽带拨号上网账号密码忘了怎么办 双眼皮割的太宽怎么办 营业执照异常名录移除注销怎么办 工商局注册后骚扰电话怎么办 单位工作失误医保断交7年怎么办 大门对大门怎么办?巧用天官赐福 委托书公司名称打错了怎么办 招行ubank不对账怎么办 信贷公司利息高不合理怎么办 衣服上的logo掉怎么办 ui设计师接不到私活怎么办 微信打开很慢怎么办 小泰迪感冒加身上结痂怎么办 法斗眼睛肿了怎么办 地图鱼身上有白点怎么办 人被广告牌砸了怎么办 小米手机出现繁体中文英文怎么办 雅思考试把姓名写错了怎么办 房贷的流水账假怎么办 报到证报道期限过期了怎么办 注销公司公章丢了怎么办 家里的猫太调皮怎么办 孩子纹身了我该怎么办 46天婴儿感冒了怎么办 狗病了不吃东西怎么办 幼儿急诊见风了怎么办