字符串[未AC](后缀自动机):HEOI 2016 str

  超级恶心,先后用set维护right,再用主席树维护,全部超时,本地测是AC的。放心,BZOJ上还是1S限制,貌似只有常数优化到一定境界的人才能AC吧。

  总之我是精神胜利了哦耶QAQ

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #define lb lower_bound
 5 #define ub upper_bound
 6 #include <set>
 7 using namespace std;
 8 const int N=200010;
 9 int fa[N][20],ch[N][2],len[N],pos[N];
10 int lst,cnt;set<int>t[N];
11 int n,Q,a,b,c,d;char s[N];
12 void Init(){lst=cnt=1;}
13 void Insert(int c){
14     int p=lst,np=lst=++cnt;len[np]=len[p]+1;
15     while(p&&ch[p][c]==0)ch[p][c]=np,p=fa[p][0];
16     if(!p)fa[np][0]=1;
17     else{
18         int q=ch[p][c],nq;
19         if(len[q]==len[p]+1)fa[np][0]=q;
20         else{
21             len[nq=++cnt]=len[p]+1;
22             fa[nq][0]=fa[q][0];fa[q][0]=fa[np][0]=nq;
23             memcpy(ch[nq],ch[q],sizeof(ch[q]));
24             while(ch[p][c]==q)ch[p][c]=nq,p=fa[p][0];
25         }
26     }
27 }
28 int cntE,fir[N],to[N],nxt[N];
29 void addedge(int a,int b){
30     nxt[++cntE]=fir[a];
31     to[fir[a]=cntE]=b;
32 }
33  
34 set<int>Merge(set<int>x,set<int>y){
35     if(x.size()<y.size())swap(x,y);
36     x.insert(y.begin(),y.end());
37     //delete &y;
38     return x;
39 }
40  
41 void DFS(int x){
42     for(int i=fir[x];i;i=nxt[i])
43         DFS(to[i]),t[x]=Merge(t[x],t[to[i]]);
44 }
45  
46 bool Judge(int p,int l,int r){
47     return t[p].lb(l)!=t[p].ub(r);
48 }
49 
50 int Find(int x,int l){
51     for(int i=17;i>=0;i--)
52         if(fa[x][i]&&len[fa[x][i]]>=l)
53             x=fa[x][i];
54     return x;        
55 }
56 
57 int Solve(){
58     int l=0,r=min(d-c,b-a)+1;
59     while(l<=r){
60         int mid=(l+r)>>1;
61         int p=Find(pos[c],mid);
62         if(Judge(p,a,b-mid+1))l=mid+1;
63         else r=mid-1;
64     }
65     return r;
66 }
67 
68 
69 int main(){
70     freopen("heoi2016_str5.in","r",stdin);
71     freopen("heoi2016_str.out","w",stdout);
72     Init();scanf("%d%d%s",&n,&Q,s+1);
73     for(int i=n;i>=1;i--){Insert(s[i]-'a');t[pos[i]=lst].insert(i);}
74     for(int i=2;i<=cnt;i++)addedge(fa[i][0],i);DFS(1);
75     for(int k=1;k<=17;k++)
76         for(int i=1;i<=cnt;i++)
77             fa[i][k]=fa[fa[i][k-1]][k-1];
78     while(Q --){
79         scanf("%d%d%d%d",&a,&b,&c,&d);
80         printf("%d
",Solve());
81     }
82     return 0;
83 }

  然后是应该AC的:

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <ctime>
 5 using namespace std;
 6 const int N=200010;
 7 int fa[N][20],ch[N][26],len[N],pos[N];
 8 int lst,cnt,n,Q;char s[N];
 9 void Init(){lst=cnt=1;}
10 void Insert(int c){
11     int p=lst,np=lst=++cnt;len[np]=len[p]+1;
12     while(p&&ch[p][c]==0)ch[p][c]=np,p=fa[p][0];
13     if(!p)fa[np][0]=1;
14     else{
15         int q=ch[p][c],nq;
16         if(len[q]==len[p]+1)fa[np][0]=q;
17         else{
18             len[nq=++cnt]=len[p]+1;
19             fa[nq][0]=fa[q][0];fa[q][0]=fa[np][0]=nq;
20             memcpy(ch[nq],ch[q],sizeof(ch[q]));
21             while(ch[p][c]==q)ch[p][c]=nq,p=fa[p][0];
22         }
23     }
24 }
25 int cntE,fir[N],to[N],nxt[N];
26 void addedge(int a,int b){
27     nxt[++cntE]=fir[a];
28     to[fir[a]=cntE]=b;
29 }
30  
31 int id[N],ed[N],tot;
32 int rt[N],sum[N*25],son[N*25][2];
33 void Insert(int pre,int &rt,int l,int r,int g){
34     sum[rt=++tot]=sum[pre]+1;
35     son[rt][0]=son[pre][0];
36     son[rt][1]=son[pre][1];
37     if(l==r)return;int mid=l+r>>1;
38     if(mid>=g)Insert(son[pre][0],son[rt][0],l,mid,g);
39     else Insert(son[pre][1],son[rt][1],mid+1,r,g);
40 }
41 int Query(int x,int l,int r,int a,int b){
42     if(l>=a&&r<=b||!sum[x])return sum[x];
43     int ret=0,mid=l+r>>1;
44     if(mid>=a)ret=Query(son[x][0],l,mid,a,b);
45     if(mid<b)ret+=Query(son[x][1],mid+1,r,a,b);
46     return ret;
47 }
48  
49 bool Judge(int p,int l,int r){
50     int A=Query(rt[l-1],1,cnt,id[p],ed[p]);
51     int B=Query(rt[r],1,cnt,id[p],ed[p]);
52     return A<B;
53 }
54 
55 int st[N],top;
56 int main(){
57     freopen("heoi2016_str.in","r",stdin);
58     freopen("heoi2016_str.out","w",stdout);
59     Init();scanf("%d%d%s",&n,&Q,s+1);
60     for(int i=n;i>=1;i--)Insert(s[i]-'a'),pos[i]=lst;
61     for(int i=2;i<=cnt;i++)addedge(fa[i][0],i);
62     for(int k=1;k<=18;k++)for(int i=1;i<=cnt;i++)
63         fa[i][k]=fa[fa[i][k-1]][k-1];
64     st[top=1]=1;
65     while(top){
66         int x=st[top];
67         if(id[x]){ed[x]=tot;top--;}
68         else{
69             id[x]=++tot;
70             for(int i=fir[x];i;i=nxt[i])
71                 st[++top]=to[i];
72         }
73     }
74     
75     tot=0;
76     for(int i=1;i<=n;i++)
77         Insert(rt[i-1],rt[i],1,cnt,id[pos[i]]);    
78     int a,b,c,d;    
79     while(Q --){
80         scanf("%d%d%d%d",&a,&b,&c,&d);
81         int l=0,r=min(d-c,b-a)+1;
82         while(l<=r){
83             int mid=l+r>>1,p=pos[c];
84             for(int i=18;i>=0;i--)
85                 if(fa[p][i]&&len[fa[p][i]]>=mid)
86                     p=fa[p][i];
87             if(Judge(p,a,b-mid+1))l=mid+1;
88             else r=mid-1;
89         }
90         printf("%d
",r);
91     }
92     //printf("%lf
", (double)clock()/CLOCKS_PER_SEC);
93     return 0;
94 }

   有毒啊,后缀数组都写挂了,TLE。

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 using namespace std;
  5 const int N=100010;
  6 int n,Q,r[N],Wa[N],Wb[N],Wv[N],Ws[N];
  7 int rk[N],sa[N],lcp[N],mm[N],Min[N][20];
  8 int len,cnt,ch[N*20][2],sum[N*20],rt[N];
  9 char s[N];
 10 bool cmp(int *p,int i,int j,int l){
 11     return p[i]==p[j]&&p[i+l]==p[j+l];
 12 }
 13 
 14 void DA(int n,int m){
 15     int i,j,p,*x=Wa,*y=Wb;
 16     for(i=0;i<m;i++)Ws[i]=0;
 17     for(i=0;i<n;i++)++Ws[x[i]=r[i]];
 18     for(i=1;i<m;i++)Ws[i]+=Ws[i-1];
 19     for(i=n-1;i>=0;i--)sa[--Ws[x[i]]]=i;
 20     
 21     for(p=1,j=1;p<n;m=p,j<<=1){
 22         for(p=0,i=n-j;i<n;i++)y[p++]=i;
 23         for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
 24         for(i=0;i<m;i++)Ws[i]=0;
 25         for(i=0;i<n;i++)++Ws[Wv[i]=x[y[i]]];
 26         for(i=1;i<m;i++)Ws[i]+=Ws[i-1];
 27         for(i=n-1;i>=0;i--)sa[--Ws[Wv[i]]]=y[i];
 28         for(swap(x,y),x[sa[0]]=0,i=1,p=1;i<n;i++)
 29             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
 30     }
 31 }
 32 
 33 void LCP(int n){
 34     int i,j,k=0;
 35     for(i=1;i<=n;i++)rk[sa[i]]=i;
 36     for(i=0;i<n;lcp[rk[i++]]=k)
 37         for(k-=k>0,j=sa[rk[i]-1];r[i+k]==r[j+k];k++);
 38 }
 39 
 40 #define mid ((l+r)>>1)
 41 void Insert(int pre,int &rt,int l,int r,int g,int d){
 42     sum[rt=++cnt]=sum[pre]+d;ch[rt][0]=ch[pre][0];
 43     ch[rt][1]=ch[pre][1];if(l==r)return;
 44     if(mid>=g)Insert(ch[pre][0],ch[rt][0],l,mid,g,d);
 45     else Insert(ch[pre][1],ch[rt][1],mid+1,r,g,d);
 46 }
 47 
 48 int Query(int pre,int rt,int l,int r,int a,int b){
 49     if(l>=a&&r<=b)return sum[rt]-sum[pre];int ret=0;
 50     if(mid>=a)ret=Query(ch[pre][0],ch[rt][0],l,mid,a,b);
 51     if(mid<b)ret+=Query(ch[pre][1],ch[rt][1],mid+1,r,a,b);
 52     return ret;
 53 }
 54 
 55 void Prepare(int n){
 56     mm[0]=-1;
 57     for(int i=1;i<=n;i++){
 58         mm[i]=mm[i-1];
 59         if(!(i&i-1))mm[i]+=1;
 60         Min[i][0]=lcp[i];
 61     }
 62     for(int k=1;k<=mm[n];k++)
 63         for(int i=1;i+(1<<k-1)<=n;i++)
 64             Min[i][k]=min(Min[i][k-1],Min[i+(1<<k-1)][k-1]);
 65 }
 66 
 67 int Qmin(int x,int y){
 68     if(x>y)swap(x,y);x+=1;int l=mm[y-x+1];
 69     return min(Min[x][l],Min[y-(1<<l)+1][l]);
 70 }
 71 
 72 int a,b,c,d,lo,hi;
 73 bool Check(int x,int n){
 74     int l=1,r=rk[c-1]-1,pl,pr;
 75     while(l<=r){
 76         if(Qmin(mid,rk[c-1])>=x)r=mid-1;
 77         else l=mid+1;    
 78     }pl=l;
 79     l=rk[c-1]+1,r=n;
 80     while(l<=r){
 81         if(Qmin(rk[c-1],mid)>=x)l=mid+1;
 82         else r=mid-1;
 83     }pr=r;
 84     return Query(rt[pl-1],rt[pr],1,n,a,b-x+1);
 85 }
 86 
 87 int main(){
 88     freopen("heoi2016_str.in","r",stdin);
 89     freopen("heoi2016_str.out","w",stdout);
 90     scanf("%d%d%s",&n,&Q,s);
 91     for(;s[len];len++)r[len]=s[len];
 92     DA(len+1,128);LCP(len);Prepare(len);
 93     for(int i=1;i<=len;i++)
 94         Insert(rt[i-1],rt[i],1,len,sa[i]+1,1);
 95     while(Q--){
 96         scanf("%d%d%d%d",&a,&b,&c,&d);
 97         lo=1,hi=min(b-a+1,d-c+1);
 98         while(lo<=hi){
 99             int MID=(lo+hi)>>1;
100             if(Check(MID,len))lo=MID+1;
101             else hi=MID-1;
102         }
103         printf("%d
",hi);
104     }
105     return 0;
106 }
原文地址:https://www.cnblogs.com/TenderRun/p/5793102.html