解题:NOI 2016 优秀的拆分

题面

其实题目不算很难,但是我调试的时候被玄学了,for循环里不写空格会RE,写了才能过。神**调了一个多小时是这么个不知道是什么的玩意(真事,可以问i207M=。=),心态爆炸

发现我们只要找AA或者BB就行了,因为另一半反过来再做一次然后拼起来就可以了,那么就设$stp[i]$表示从$i$开始有多少个$AA$这样的串,$edp[i]$表示在$i$结束有多少个$AA$这样的串。一个个位置暴力求是$O(n^2)$的,可以得95pts(雾。

AC做法是一种巧妙(套路?毕竟我做题少)的做法。枚举一个len把串分成长度为$len$的段,然后发现形如$AA$的字符串一定至少跨过了两个分界点,那么我们求一下这两个分界点的$LCP$和$LCS$,看看是不是超过$len$即可,然后具体的贡献可以用差分实现,时间复杂度$O(n\log n)$(不知道为啥$n$只出了30000,可能是为了放哈希+二分的$O(n\log^2 n)$过去?)。

  1 #include<cmath>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 const int N=30005,K=16;
  7 struct a
  8 {
  9     char str[N];
 10     int sec[N],bkt[N];
 11     int sar[N],rnk[N],hgt[N],st[N][K];
 12     int len,siz;
 13     void Set()
 14     {
 15         len=0,siz=30;
 16         memset(sec,0,sizeof sec);
 17         memset(rnk,0,sizeof rnk);
 18     }
 19     void Prework()
 20     {
 21         register int i;
 22         for(i=1;i<=len;i++)
 23             rnk[i]=str[i]-'a'+1,sec[i]=i;
 24     }
 25     void Basenum_Sort()
 26     {
 27         register int i;
 28         for(i=1;i<=siz;++i) bkt[i]=0;
 29         for(i=1;i<=len;++i) ++bkt[rnk[i]];
 30         for(i=1;i<=siz;++i) bkt[i]+=bkt[i-1];
 31         for(i=len;i>=1;--i) sar[bkt[rnk[sec[i]]]--]=sec[i];
 32     }   
 33     void Suffix_Sort()
 34     {
 35         register int i;
 36         int cnt=0,pw=1;
 37         Basenum_Sort();
 38         while(cnt<len)
 39         {
 40             cnt=0;
 41             for(i=1;i<=pw;i++) sec[++cnt]=len-pw+i;
 42             for(i=1;i<=len;i++) if(sar[i]>pw) sec[++cnt]=sar[i]-pw;
 43             Basenum_Sort(); swap(rnk,sec); rnk[sar[1]]=cnt=1;
 44             for(i=2;i<=len;i++)
 45                 cnt+=(sec[sar[i-1]]!=sec[sar[i]]||sec[sar[i-1]+pw]!=sec[sar[i]+pw]),rnk[sar[i]]=cnt;
 46             pw<<=1,siz=cnt;
 47         }
 48     }
 49     void Getting_Height()
 50     {
 51         register int i,p=0;
 52         for(i=1;i<=len;i++)
 53             if(rnk[i]!=1)
 54             {
 55                 int r=sar[rnk[i]-1];
 56                 while(str[r+p]==str[i+p]) p++;
 57                 hgt[rnk[i]]=p; if(p>0) p--; 
 58             }
 59         hgt[1]=0;
 60     }
 61     void Building_Table()
 62     {
 63         register int i,j;
 64         for(i=1;i<=len;i++)
 65             st[i][0]=hgt[i];
 66         int lgg=log2(len);
 67         for(i=1;i<=lgg;i++)
 68             for(j=1;j<=len-(1<<i)+1;j++)
 69                 st[j][i]=min(st[j][i-1],st[j+(1<<(i-1))][i-1]);
 70     }
 71     int LCP_Query(int x,int y)
 72     {
 73         int xx=rnk[x],yy=rnk[y],lgg;
 74         if(xx>yy) swap(xx,yy); xx++,lgg=log2(yy-xx+1); 
 75         return min(st[xx][lgg],st[yy-(1<<lgg)+1][lgg]);
 76     }
 77 }SA[2];
 78 int n,lth,stp[N],edp[N];
 79 void Init()
 80 {
 81     SA[0].Set(),SA[1].Set();
 82     memset(stp,0,sizeof stp);
 83     memset(edp,0,sizeof edp);
 84 }
 85 int main()
 86 {
 87     register int i,j,k,h;
 88     scanf("%d",&n);
 89     for(i=1;i<=n;i++)
 90     {
 91         Init(); scanf("%s",SA[0].str+1);
 92         SA[0].len=SA[1].len=lth=strlen(SA[0].str+1);
 93         for(j=1;j<=lth;j++)
 94             SA[1].str[j]=SA[0].str[lth-j+1];
 95         for(j=0;j<=1;j++)
 96         {
 97             SA[j].Prework();
 98             SA[j].Suffix_Sort();
 99             SA[j].Getting_Height();
100             SA[j].Building_Table();
101         }
102         for(j=1;j<=lth/2;j++)
103         {
104             for(k=j,h=2*j;h<=lth;k+=j,h+=j)
105             {
106                 int l1=min(SA[0].LCP_Query(k,h),j);
107                 int l2=min(SA[1].LCP_Query(lth-k+1,lth-h+1),j);
108                 if(l1+l2>j)
109                 {
110                     stp[k-l2+1]++,edp[h-l2+j]++;
111                     stp[k+l1-j+1]--,edp[h+l1]--;
112                 }
113             }
114         }
115         long long ans=0;
116         for(j=1;j<=lth;j++) 
117             stp[j]+=stp[j-1],edp[j]+=edp[j-1];
118         for(j=1;j<lth;j++)
119             ans+=1ll*stp[j+1]*edp[j];
120         printf("%lld\n",ans);
121     }
122     return 0;
123 }
View Code

猜你喜欢

转载自www.cnblogs.com/ydnhaha/p/10148244.html