zoukankan      html  css  js  c++  java
  • poj1226 Substrings

    2333

    这个就是把每一个串正反连起来,然后所有串连起来,注意中间加上分割的分开(应该开的比z大,而且蛋疼的我写int)

    然后搞出后缀数组,二分一个答案,然后再height数组判断一下就好了

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <cstring>
      4 #define N 100005
      5 #define inf 0x3f3f3f3f
      6 #define LL long long
      7 #define eps 1e-8
      8 using namespace std;
      9 inline int ra()
     10 {
     11     int x=0,f=1; char ch=getchar();
     12     while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
     13     while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
     14     return x*f;
     15 }
     16 
     17 const int maxn=10005;
     18 
     19 int sa[2][maxn],rank[2][maxn],v[maxn],height[maxn],p=0,q=1;
     20 int n,len,id[maxn];
     21 int a[maxn];
     22 bool vis[105];
     23 
     24 void cal_sa(int sa[N], int rank[N], int Sa[N], int Rank[N], int k)
     25 {
     26     for (int i=1; i<=n; i++) v[rank[sa[i]]]=i;
     27     for (int i=n; i>=1; i--) if (sa[i]>k) Sa[v[rank[sa[i]-k]]--]=sa[i]-k;
     28     for (int i=n-k+1; i<=n; i++) Sa[v[rank[i]]--]=i;
     29     for (int i=1; i<=n; i++) Rank[Sa[i]]=Rank[Sa[i-1]]+(rank[Sa[i]]!=rank[Sa[i-1]] || rank[Sa[i]+k]!=rank[Sa[i-1]+k]);
     30 }
     31 void get_height()
     32 {
     33     int k=0;
     34     for (int i=1; i<=n; i++)
     35     {
     36         if (rank[p][i]==1) height[1]=0;
     37         else
     38         {
     39             int j=sa[p][rank[p][i]-1];
     40             while (a[j+k]==a[i+k]) k++;
     41             height[rank[p][i]]=k;
     42             if (k) k--;
     43         }
     44     }
     45 }
     46 void work()
     47 {
     48     for (int i=1; i<=n; i++) v[a[i]]++;
     49     for (int i=1; i<=300; i++) v[i]+=v[i-1];
     50     for (int i=1; i<=n; i++) sa[p][v[a[i]]--]=i;
     51     for (int i=1; i<=n; i++) rank[p][sa[p][i]]=rank[p][sa[p][i-1]]+(a[sa[p][i]]!=a[sa[p][i-1]]);
     52     for (int k=1; k<n; k<<=1,swap(p,q)) cal_sa(sa[p],rank[p],sa[q],rank[q],k);
     53     get_height();
     54 }
     55 
     56 bool check(int L)
     57 {
     58     int tot=0; memset(vis,0,sizeof(vis));
     59     for (int i=2; i<=n; i++)
     60     {
     61         if (height[i]<L)
     62         {
     63             tot=0; memset(vis,0,sizeof(vis));
     64             continue;
     65         }
     66         if (!vis[id[sa[p][i-1]]]) vis[id[sa[p][i-1]]]=1,tot++;
     67         if (!vis[id[sa[p][i]]]) vis[id[sa[p][i]]]=1,tot++;
     68         if (tot>=len) return 1;
     69     }
     70     return 0;
     71 }
     72 void solve()
     73 {
     74     int l=0,r=n,ans=0;
     75     while (l<=r)
     76     {
     77         int mid=l+r>>1;
     78         if (check(mid)) ans=mid,l=mid+1; else r=mid-1;
     79     }
     80     printf("%d
    ",ans);
     81 }
     82 int main(int argc, char const *argv[])
     83 {
     84     int T=ra();
     85     while (T--)
     86     {
     87         memset(v,0,sizeof(v)); n=ra(); len=0;
     88         for (int i=1; i<=n; i++)
     89         {
     90             char ch[105]; scanf("%s",ch+1);
     91             for (int j=1; j<=strlen(ch+1); j++)
     92                 a[++len]=ch[j],id[len]=i;
     93             a[++len]=150+(i-1)*2,id[len]=i;
     94             for (int j=strlen(ch+1); j>=1; j--)
     95                 a[++len]=ch[j],id[len]=i;
     96             a[++len]=150+(i-1)*2+1,id[len]=i;
     97         }
     98         swap(n,len); work();
     99         solve();
    100     }
    101     return 0;
    102 }
  • 相关阅读:
    信息安全学习笔记1
    Linux学习笔记4------磁盘分区(问答形式)
    Linux学习笔记3-------添加磁盘并分区
    用for循环打印三角形
    包机制
    运算符
    变量、常量、作用域
    数据类型转换
    数据的基本类型
    Java运行原理的简单理解
  • 原文地址:https://www.cnblogs.com/ccd2333/p/6642213.html
Copyright © 2011-2022 走看看