解题:USACO06DEC Milk Patterns

题面

初见SA

用了一个常见的按$height$分组的操作:二分答案,然后按$height$分组,遇到一个$height$小于$mid$的就丢进下一组并更新答案,如果最多的那组不少于$k$个说明可行

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=20005;
 6 int uni[N],num[N],sec[N],bkt[N];
 7 int SA[N],rnk[N],hgt[N];
 8 int n,k,l,r,ans,siz;
 9 void Basenum_Sort()
10 {
11     register int i;
12     for(i=1;i<=siz;i++) bkt[i]=0;
13     for(i=1;i<=n;i++) bkt[rnk[i]]++;
14     for(i=1;i<=siz;i++) bkt[i]+=bkt[i-1];
15     for(i=n;i;i--) SA[bkt[rnk[sec[i]]]--]=sec[i];
16 }
17 void Suffix_Sort()
18 {
19     register int i;
20     int pw=1,cnt=0;
21     Basenum_Sort();
22     while(cnt<n)
23     {
24         cnt=0;
25         for(i=1;i<=pw;i++) sec[++cnt]=n-pw+i;
26         for(i=1;i<=n;i++) if(SA[i]>pw) sec[++cnt]=SA[i]-pw;
27         Basenum_Sort(); swap(rnk,sec); rnk[SA[1]]=cnt=1;
28         for(i=2;i<=n;i++) cnt+=(sec[SA[i-1]]!=sec[SA[i]]||sec[SA[i-1]+pw]!=sec[SA[i]+pw]),rnk[SA[i]]=cnt;
29         pw<<=1,siz=cnt;
30     }
31 }
32 void Getting_Height()
33 {
34     int p=0;
35     for(int i=1;i<=n;i++)
36         if(rnk[i]!=1)
37         {
38             int r=SA[rnk[i]-1];
39             while(num[r+p]==num[i+p]) p++;
40             hgt[rnk[i]]=p; if(p>0) p--;
41         }
42     hgt[1]=0;
43 }
44 bool check(int x)
45 {
46     register int i;
47     int len=0,lst=1;
48     for(i=1;i<=n;i++)
49         if(hgt[i]<x) 
50             len=max(i-lst,len),lst=i;
51     len=max(n-lst+1,len);
52     return len>=k;
53 }
54 int main()
55 {
56     register int i;
57     scanf("%d%d",&n,&k);
58     for(i=1;i<=n;i++)
59         scanf("%d",&num[i]),uni[i]=num[i];
60     sort(uni+1,uni+1+n),siz=unique(uni+1,uni+1+n)-uni-1;
61     for(i=1;i<=n;i++)
62         rnk[i]=lower_bound(uni+1,uni+1+siz,num[i])-uni,sec[i]=i;
63     Suffix_Sort(); Getting_Height(); l=0,r=n; 
64     while(l<=r)
65     {
66         int mid=(l+r)/2;
67         if(check(mid)) ans=mid,l=mid+1;
68         else r=mid-1;
69     }
70     printf("%d",ans);
71     return 0;
72 }
View Code

Upd:SAM对SA的全面替换已完成

这题丢给SAM就没啥可说的了,直接按定义来就行

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<unordered_map>
 5 #define umap unordered_map
 6 using namespace std;
 7 const int N=40005;
 8 umap<int,int> trs[N];
 9 int p[N],noww[N],goal[N];
10 int fth[N],len[N],siz[N];
11 int rd,lth,kth,cnt,tot,lst,ans; 
12 void Link(int f,int t)
13 {
14     noww[++cnt]=p[f];
15     goal[cnt]=t,p[f]=cnt;
16 }
17 void Insert(int ch)
18 {
19     int nde=lst,newn=++tot; lst=newn;
20     siz[newn]=1,len[newn]=len[nde]+1;
21     while(nde&&!trs[nde].count(ch))
22         trs[nde][ch]=newn,nde=fth[nde];
23     if(!nde) fth[newn]=1;
24     else 
25     {
26         int tran=trs[nde][ch];
27         if(len[tran]==len[nde]+1)
28             fth[newn]=tran;
29         else 
30         {
31             int rnde=++tot; 
32             len[rnde]=len[nde]+1,trs[rnde]=trs[tran];
33             fth[rnde]=fth[tran],fth[tran]=fth[newn]=rnde;
34             while(nde&&trs[nde][ch]==tran)
35                 trs[nde][ch]=rnde,nde=fth[nde];
36         }
37     }
38 }
39 void DFS(int nde)
40 {
41     for(int i=p[nde];i;i=noww[i])
42         DFS(goal[i]),siz[nde]+=siz[goal[i]];
43 }
44 int main()
45 {
46     register int i;
47     scanf("%d%d",&lth,&kth),lst=tot=1;
48     for(i=1;i<=lth;i++) scanf("%d",&rd),Insert(rd);
49     for(i=1;i<=tot;i++) Link(fth[i],i); DFS(1);
50     for(i=1;i<=tot;i++)    
51         if(siz[i]>=kth) ans=max(ans,len[i]);
52     printf("%d",ans);
53     return 0;
54 }
View Code

 

posted @ 2018-12-13 20:55  Speranza_Leaf  阅读(116)  评论(0)    收藏  举报