• SPOJ220 Relevant Phrases of Annihilation


    http://www.spoj.com/problems/PHRASES/

    题意:给n个串,求n个串里面都有2个不重叠的最长的字串长度。

    思路:二分答案,然后就可以嘿嘿嘿

    PS:辣鸡题目毁我青春,一开始二分的时候ans没有赋初值为0,结果没答案的时候就会输出奇怪的数字T_T,其实主要还是怪我不小心。。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 int len,num[500005],ws[500005],wv[500005],wa[500005],wb[500005],h[500005],sa[500005],rank[500005];
     7 int f[500005][2],N,b[500005];
     8 char s[500005];
     9 int read(){
    10     int t=0,f=1;char ch=getchar();
    11     while (ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();}
    12     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
    13     return t*f;
    14 }
    15 bool cmp(int *r,int a,int b,int l){
    16     return r[a]==r[b]&&r[a+l]==r[b+l];
    17 }
    18 void da(int *r,int *sa,int n,int m){
    19     int *t,*x=wa,*y=wb,i,j,k,p;
    20     for (i=0;i<m;i++) ws[i]=0;
    21     for (i=0;i<n;i++) x[i]=r[i];
    22     for (i=0;i<n;i++) ws[x[i]]++;
    23     for (i=1;i<m;i++) ws[i]+=ws[i-1];
    24     for (i=n-1;i>=0;i--) sa[--ws[x[i]]]=i;
    25     for (j=1,p=1;p<n;j*=2,m=p){
    26         for (p=0,i=n-j;i<n;i++) y[p++]=i;
    27         for (i=0;i<n;i++) if (sa[i]>=j) y[p++]=sa[i]-j;
    28         for (i=0;i<m;i++) ws[i]=0;
    29         for (i=0;i<n;i++) wv[i]=x[y[i]];
    30         for (i=0;i<n;i++) ws[wv[i]]++;
    31         for (i=1;i<m;i++) ws[i]+=ws[i-1];
    32         for (i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i];
    33         for (t=x,x=y,y=t,i=1,x[sa[0]]=0,p=1;i<n;i++){
    34             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    35         }
    36     }
    37 }
    38 void cal(int *r,int n){
    39     int i,j,k=0;
    40     for (int i=1;i<=n;i++) rank[sa[i]]=i;
    41     for (int i=0;i<n;h[rank[i++]]=k){
    42         for (k?k--:0,j=sa[rank[i]-1];r[j+k]==r[i+k];k++);
    43     }
    44 }
    45 bool check(int mid){
    46     int l,r;
    47     for (int i=1;i<=len;i++){
    48         l=i;
    49         while (l<=len&&h[l]<mid) l++;
    50         r=l;
    51         while (r<=len&&h[r]>=mid) r++;
    52         for (int j=1;j<=N;j++) f[j][0]=0x3f3f3f3f,f[j][1]=-0x3f3f3f3f;
    53         for (int j=l-1;j<=r-1;j++){
    54             int k=b[sa[j]];
    55             if (k==N+1) continue;
    56             f[k][0]=std::min(f[k][0],sa[j]);
    57             f[k][1]=std::max(f[k][1],sa[j]);
    58         }
    59         int j=0;
    60         for (j=1;j<=N;j++){
    61             if (f[j][0]==0x3f3f3f3f) break;
    62             if (f[j][1]-f[j][0]<mid) break;
    63         }
    64         if (j>N) return 1;
    65         i=r;
    66     }
    67     return 0;
    68 }
    69 void solve(){
    70     int l=1,r=20000,ans=0;
    71     while (l<=r){
    72         int mid=(l+r)>>1;
    73         if (check(mid)) ans=mid,l=mid+1;
    74         else r=mid-1;
    75     }
    76     printf("%d ",ans);
    77 }
    78 int main(){
    79     int T=read();
    80     while (T--){
    81         len=0;
    82         int n=read();
    83         for (int i=1;i<=n;i++){
    84             scanf("%s",s+1);
    85             int Len=strlen(s+1);
    86             for (int j=1;j<=Len;j++)
    87              num[len]=s[j],b[len++]=i;
    88             if (i<n) num[len]=290+i,b[len++]=n+1; 
    89         }
    90         num[len]=0;b[len]=n+1;
    91         da(num,sa,len+1,310);
    92         cal(num,len);
    93         N=n;
    94         solve();
    95     }
    96 }
  • 相关阅读:
    oracle查看所有角色
    jQuery 异步提交表单实例解析
    oracle查看用户系统权限
    js中日期操作大全
    oracle 查询用户下所有表
    JS语法字典
    JS定时器例子讲解
    开源软件
    rpm的使用
    lvs+keepalived和haproxy+heartbeat区别
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5636269.html
Copyright © 2020-2023  润新知