您的位置:首页 > 其它

【SPOJ220】Relevant Phrases of Annihilation(后缀数组,二分)

2018-09-14 20:32 417 查看

题意:

n<=10,len<=1e4

思路:

1 #include<cstdio>
2 #include<cstring>
3 #include<string>
4 #include<cmath>
5 #include<iostream>
6 #include<algorithm>
7 #include<map>
8 #include<set>
9 #include<queue>
10 #include<vector>
11 using namespace std;
12 typedef long long ll;
13 typedef unsigned int uint;
14 typedef unsigned long long ull;
15 typedef pair<int,int> PII;
16 typedef vector<int> VI;
17 #define fi first
18 #define se second
19 #define MP make_pair
20 #define N   210000
21 #define MOD 1000000007
22 #define eps 1e-8
23 #define pi acos(-1)
24 #define oo  1000000000
25
26 char ch
;
27
28 int n,i,s
,sa
,wa
,wb
,wc
,wd
,height
,rank
,
29     a
,b
,c
,d
,num
,M;
30
31 int read()
32 {
33    int v=0,f=1;
34    char c=getchar();
35    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
36    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
37    return v*f;
38 }
39
40 bool cmp(int *r,int a,int b,int l)
41 {
42     return r[a]==r[b]&&r[a+l]==r[b+l];
43 }
44
45 void getsa(int *r,int *sa,int n,int m)
46 {
47     int *x=wa,*y=wb,j,p;
48     for(i=0;i<n;i++) wc[x[i]=r[i]]++;
49     for(i=1;i<m;i++) wc[i]+=wc[i-1];
50     for(i=n-1;i>=0;i--) sa[--wc[x[i]]]=i;
51     for(j=1,p=1;p<n;j*=2,m=p)
52     {
53         p=0;
54         for(i=n-j;i<n;i++) y[p++]=i;
55         for(i=0;i<n;i++)
56          if(sa[i]>=j) y[p++]=sa[i]-j;
57         for(i=0;i<n;i++) wd[i]=x[y[i]];
58         for(i=0;i<m;i++) wc[i]=0;
59         for(i=0;i<n;i++) wc[wd[i]]++;
60         for(i=1;i<m;i++) wc[i]+=wc[i-1];
61         for(i=n-1;i>=0;i--) sa[--wc[wd[i]]]=y[i];
62         swap(x,y);
63         p=1; x[sa[0]]=0;
64         for(i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
65     }
66 }
67
68 void getheight(int *r,int *sa,int n)
69 {
70     int i,j,k=0;
71     for(i=1;i<=n;i++) rank[sa[i]]=i;
72     for(i=0;i<n;height[rank[i++]]=k)
73     {
74         if(k) k--;
75         j=sa[rank[i]-1];
76         while(r[i+k]==r[j+k]) k++;
77     }
78 }
79
80 void init()
81 {
82         memset(s,0,sizeof(s));
83         memset(sa,0,sizeof(sa));
84         memset(wa,0,sizeof(wa));
85         memset(wb,0,sizeof(wb));
86         memset(wc,0,sizeof(wc));
87         memset(wd,0,sizeof(wd));
88         memset(height,0,sizeof(height));
89         memset(rank,0,sizeof(rank));
90 }
91
92 bool isok(int K)
93 {
94     int i=1;
95     while(i<n)
96     {
97         i++;
98         if(height[i]>=K)
99         {
100             int st=i;
101             while(i<=n&&height[i]>=K) i++;
102             if(st<=i-1)
103             {
104                 int ed=i-1;
105                 for(int j=1;j<=M;j++)
106                 {
107                     b[j]=0;
108                     c[j]=oo;
109                     d[j]=-oo;
110                 }
111                 for(int j=st-1;j<=ed;j++)
112                 {
113                     int t=num[sa[j]];
114                     b[t]++;
115                     c[t]=min(c[t],sa[j]);
116                     d[t]=max(d[t],sa[j]);
117                 }
118                 int flag=1;
119                 for(int j=1;j<=M;j++)
120                 {
121                       if(b[j]<2){flag=0; break;}
122                       if(d[j]-c[j]<K){flag=0; break;}
123                 }
124                 if(flag) return 1;
125             }
126         }
127     }
128     return 0;
129 }
130
131 int main()
132 {
133     freopen("spoj220.in","r",stdin);
134     freopen("spoj220.out","w",stdout);
135     int cas;
136     scanf("%d",&cas);
137     while(cas--)
138     {
139         init();
140         scanf("%d",&M);
141         n=-1;
142         for(int i=1;i<=M;i++)
143         {
144             scanf("%s",ch);
145             int t=strlen(ch);
146             for(int j=0;j<t;j++)
147             {
148                 s[++n]=ch[j]-'a'+20;
149                 num
=i;
150             }
151             s[++n]=i;
152             num
=0;
153         }
154         getsa(s,sa,n+1,100);
155         getheight(s,sa,n);
156     //    printf("1\n");
157         int L=1;
158         int R=10000;
159         int last=0;
160         while(L<=R)
161         {
162             int mid=(L+R)>>1;
163             if(isok(mid)){last=mid; L=mid+1;}
164              else R=mid-1;
165         }
166         printf("%d\n",last);
167     }
168     return 0;
169 }
170

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: