• uva11107 后缀数组


    题意给了n个串 然后计算 这些串中的子串在大于1/2的串中出现 求出这个串的最长长度。 将这些串用一个每出现的不同的字符拼起来 ,然后二分找lcp

    #include <iostream>
    #include <algorithm>
    #include <string.h>
    #include <algorithm>
    #include <vector>
    #include <cstdio>
    using namespace std;
    const int maxn=2005;
    const int maxm=205;
    const int MM=maxn*maxm;
    struct SuffixArray
    {
      int s[MM];      // 原始字符数组(最后一个字符应必须是0,而前面的字符必须非0)
      int sa[MM];     // 后缀数组
      int rank[MM];   // 名次数组. rank[0]一定是n-1,即最后一个字符
      int height[MM]; // height数组
      int t[MM], t2[MM], c[MM]; // 辅助数组
      int n; // 字符个数
         void clear(){ n=0; }
      void build(int m)
      {
          int *x=t,*y=t2,i;
          for(i=0; i<m; i++)c[i]=0;
          for(i=0; i<n; i++)c[ x[i] = s[i] ]++;
          for(i=1; i<m; i++)c[ i ] += c[ i-1 ];
         for(i = n-1; i >= 0; i--) sa[--c[x[i]]] = i;
          for(int k=1; k<=n; k<<=1)
          {
               int p=0;
               for(i=n-k; i<n; i++)y[p++]=i;
               for(i=0; i<n; i++)if(sa[i]>=k)y[p++]=sa[i]-k;
               for(i=0; i<m; i++)c[i]=0;
               for(i=0; i<n; i++)c[  x[y[ i] ] ]++;
               for(i=1; i<m; i++)c[i]+=c[i-1];
               for(i =n-1; i>=0; i--)sa[  --c[ x[ y[i] ]  ]  ] = y[i];
               swap(x,y);
               p=1;
               x[ sa[0] ] =0;
               for( i=1; i<n; i++) x[ sa[i] ]= y[ sa[i] ]==y[sa[i-1]] && y[ sa[i]+k ]== y[ sa[i-1] +k ]?p-1:p++;
               if(p>=n)break;
               m=p;
          }
      }
       void build_height() {
        int i,  k = 0;
        for(i = 0; i < n; i++) rank[sa[i]] = i;
        height[0]=0;
        for(i = 0; i < n; i++) {
          if(k) k--;
          if(rank[i]==0)continue;
          int j = sa[rank[i]-1];
          while(i+k<n&&j+k<n&&s[i+k] == s[j+k]) k++;
          height[rank[i]] = k;
        }
      }
    }sa;
    char word[MM];
    int idx[MM],n,maxlen;
    int flag[150];
    void add(int ch, int i)
    {
      idx[sa.n] = i;
      sa.s[sa.n++] = ch;
    }
    // 子串[L,R) 是否符合要求
    bool good(int L, int R,int &ss)
    {
    
      if(R - L <= n/2) return false;
      int cnt = 0;
      for(int i = L; i < R; i++) {
        int x = idx[sa.sa[i]];
        if(x != n && flag[x]!=ss) { flag[x] = ss; cnt++; }
      }
      return cnt > n/2;
    }
    
    void print_sub(int L, int R)
    {
      for(int i = L; i < R; i++)
        printf("%c", sa.s[i] - 1 + 'a');
      printf("
    ");
    }
    int ss;
    bool print_solutions(int len, bool print)
    {
      int L = 0;
    ss++;
      for(int R = 1; R <= sa.n; R++) {
        if(R == sa.n || sa.height[R] < len) { // 新开一段
          if(good(L, R,ss)) {
            if(print) print_sub(sa.sa[L], sa.sa[L] + len); else return true;
          }
          ss++;
          L = R;
        }
      }
      return false;
    }
    
    void solve(int maxlen)
    {
      if(!print_solutions(1, false))
        printf("?
    ");
      else {
        int L = 1, R = maxlen, M;
        while(L < R) {
          M = L + (R-L+1)/2;
          if(print_solutions(M, false)) L = M;
          else R = M-1;
        }
        print_solutions(L, true);
      }
    }
    
    int main()
    {
        int kase=0;
        while(scanf("%d",&n)==1)
            {
                 if(n==0)break;
                 if(kase++>0) puts("");
                   maxlen=0;
                  sa.clear();
                  for(int i=0; i<n; i++)
                    {
                        scanf("%s",word);
                        int sz= strlen(word);
                        maxlen=max(sz,maxlen);
                        for(int j=0; j<sz; j++)
                            {
                                add(word[j]-'a'+1,i);
                            }
                        add(123+i,n);
                    }
                    add(123+n,n);
                    if(n==1)printf("%s
    ",word);
                    else
                        {
                            ss=1;
                            memset(flag,0,sizeof(flag));
                            sa.build( 123+n+4 );
                            sa.build_height();
                            solve(maxlen);
                        }
            }
        return 0;
    }
    View Code
  • 相关阅读:
    2014/11/25 函数
    2014/11/24 条件查询
    2、计算器
    1、winform数据库调用(基本方法)
    1、网页基础
    14、函数输出参数、递归
    13、C#简易版 推箱子游戏
    12、函数
    11、结构体、枚举
    10、特殊集合
  • 原文地址:https://www.cnblogs.com/Opaser/p/4503350.html
Copyright © 2020-2023  润新知