UVA 11739 Giving Candies
求最大的公共前缀;
用后缀数组做;
其实暴力也可以过;
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define maxn 2009 5 using namespace std; 6 7 int s[maxn]; 8 int sa[maxn],t[maxn],t2[maxn],c[maxn],n; 9 10 void build_sa(int m) 11 { 12 int *x=t,*y=t2; 13 for(int i=0; i<m; i++)c[i]=0; 14 for(int i=0; i<n; i++)c[x[i]=s[i]]++; 15 for(int i=1; i<m; i++)c[i]+=c[i-1]; 16 for(int i=n-1; i>=0; i--)sa[--c[x[i]]]=i; 17 for(int k=1; k<=n; k<<=1) 18 { 19 int p=0; 20 for(int i=n-k; i<n; i++)y[p++]=i; 21 for(int i=0; i<n; i++)if(sa[i]>=k)y[p++]=sa[i]-k; 22 for(int i=0; i<m; i++)c[i]=0; 23 for(int i=0; i<n; i++)c[x[y[i]]]++; 24 for(int i=0; i<m; i++)c[i]+=c[i-1]; 25 for(int i=n-1; i>=0; i--)sa[--c[x[y[i]]]]=y[i]; 26 swap(x,y); 27 p=1; 28 x[sa[0]]=0; 29 for(int i=1; i<n; i++) 30 x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; 31 if(p>=n)break; 32 m=p; 33 } 34 } 35 36 int rank[maxn],height[maxn]; 37 void getheight() 38 { 39 int k=0; 40 for(int i=0; i<n; i++)rank[sa[i]]=i; 41 for(int i=0; i<n; i++) 42 { 43 if(k)k--; 44 int j=sa[rank[i]-1]; 45 while(s[i+k]==s[j+k])k++; 46 height[rank[i]]=k; 47 } 48 } 49 50 bool check(int mid) 51 { 52 int mi=99999,ma=-1; 53 for(int i=1; i<n; i++) 54 { 55 if(height[i]>=mid) 56 { 57 mi=min(mi,sa[i]); 58 ma=max(ma,sa[i]); 59 } 60 else 61 { 62 if(ma-mi>=mid)return 1; 63 mi=ma=sa[i]; 64 } 65 } 66 if(ma-mi>=mid)return 1; 67 return 0; 68 } 69 70 bool isbad[150]; 71 char bad[1005],good[1005]; 72 int main() 73 { 74 int tt,r,ca=1; 75 scanf("%d",&tt); 76 getchar(); 77 while(tt--) 78 { 79 memset(isbad,0,sizeof isbad); 80 gets(good); 81 gets(bad); 82 int l=strlen(bad); 83 for(int i=0; bad[i]!='\0'; i++) 84 isbad[bad[i]]=1; 85 n=strlen(good); 86 while(n>0&&good[n-1]==' ') 87 { 88 good[n-1]='\0'; 89 --n; 90 } 91 int xx='z'; 92 for(int i=0; good[i]!='\0'; i++) 93 { 94 if(isbad[good[i]])s[i]=xx++; 95 else s[i]=good[i]; 96 } 97 s[n]=0; 98 if (n<=1) 99 { 100 printf("Case #%d: 0\n",ca++); 101 continue; 102 } 103 n++; 104 build_sa(xx+3); 105 getheight(); 106 l=0,r=n>>1; 107 while(l<=r) 108 { 109 int mid=(l+r)>>1; 110 if(check(mid))l=mid+1; 111 else r=mid-1; 112 } 113 printf("Case #%d: %d\n",ca++,r); 114 } 115 return 0; 116 }