zoukankan      html  css  js  c++  java
  • 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



    题意:
    要求全部正向或者反向出如今超过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
    ",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] = '';
                            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
    ");
            else
            {
                for(it = ans.begin(); it!=ans.end(); it++)
                {
                    printf("%s
    ",it->first.c_str());
                }
            }
        }
    
        return 0;
    }
    


  • 相关阅读:
    LINQ进阶(深入理解C#)11 查询表达式和LINQ to Objects
    (转)Dinktopdf在.net core项目里将Html转成PDF(支持liunx)
    asp.net core 实现 face recognition 使用 tensorflowjs(源代码)
    fastreport-使用JSON做为数据源报表
    分享我的第一个RPA练习
    关于性能优化技巧
    Sql 增删改查语句
    将结果集插入另一个表中
    Vue+elementUI 表格 增删改查 纯前端 最终版
    【JAVA】使用IntelliJ IDEA创建 maven的quickStart项目
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5180995.html
Copyright © 2011-2022 走看看