日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

P1117-[NOI2016]优秀的拆分【SA】

發布時間:2023/12/3 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P1117-[NOI2016]优秀的拆分【SA】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題

題目鏈接:https://www.luogu.com.cn/problem/P1117


題目大意

長度為nnn的字符串,求所有子串有多少種分割成AABBAABBAABB的方式。


解題思路

aia_iai?表示以iii結尾的子串中有多少種分割成AAAAAA的方式
bib_ibi?表示以iii開頭的子串中有多少種分割成AAAAAA的方式

然后答案就是∑i=1n?1aibi+1\sum_{i=1}^{n-1}a_ib_{i+1}i=1n?1?ai?bi+1?

考慮用SASASA來計算a,ba,ba,b

枚舉長度lenlenlen,考慮所有長度為2?len2*len2?lenAAAAAA串,我們沒隔lenlenlen格放置一個點,那么每個串必定經過了兩個點,現在考慮求出相鄰兩個點之間的貢獻

對于相鄰兩個點l,rl,rl,r,求出它們的LCPLCPLCPLCSLCSLCS,分情況討論

  • LCP+LCS<len:LCP+LCS<len:LCP+LCS<len:那么我們可以發現沒有任何一個串2?len2*len2?lenAAAAAA串同時經過這兩個點,因為在lll的右邊和rrr的左邊,這兩個串必定有一個地方不同。
  • LCP+LCS≥len:LCP+LCS\geq len:LCP+LCSlen:那么此時有串經過這兩個點,且
    s≥l?LCP+1,t≤r+LCPs\geq l-LCP+1,t\leq r+LCPsl?LCP+1,tr+LCP的串都滿足條件
  • 時間復雜度:O(nlog?n):O(n\log n):O(nlogn)


    codecodecode

    #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=2e5+10; int T,n; long long ans,a[N],b[N]; struct SA{char s[N];int m,sa[N],rk[N],height[N],lg[N];int c[N],x[N],y[N],st[N][25];void Qsort(){for(int i=1;i<=m;i++) c[i]=0;for(int i=1;i<=n;i++) c[x[i]]++;for(int i=1;i<=m;i++) c[i]+=c[i-1];for(int i=n;i>=1;i--) sa[c[x[y[i]]]--]=y[i],y[i]=0;return;}void Get_SA(){m=256;for(int i=1;i<=n;i++)x[i]=s[i],y[i]=i;Qsort();for(int w=1;w<=n;w<<=1){int p=0;for(int i=n-w+1;i<=n;i++) y[++p]=i;for(int i=1;i<=n;i++)if(sa[i]>w) y[++p]=sa[i]-w;Qsort();swap(x,y);x[sa[1]]=p=1;for(int i=2;i<=n;i++)x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+w]==y[sa[i-1]+w])?p:++p;if(p==n) break;m=p;}return;}void Get_Height(){int k=0;for(int i=1;i<=n;i++)rk[sa[i]]=i;for(int i=1;i<=n;i++){if(rk[i]==1) continue;if(k)k--;int j=sa[rk[i]-1];while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k]) k++;height[rk[i]]=k;}return;}void Get_ST(){lg[0]=-1;for(int i=1;i<=n;i++)lg[i]=lg[i>>1]+1,st[i][0]=height[i];for(int j=1;(1<<j)<=n;j++)for(int i=1;i+(1<<j)-1<=n;i++)st[i][j]=min(st[i+(1<<(j-1))][j-1],st[i][j-1]);return;}void Build(){memset(rk,0,sizeof(rk));memset(st,0,sizeof(st));memset(height,0,sizeof(height));memset(sa,0,sizeof(sa));memset(x,0,sizeof(x));memset(y,0,sizeof(y));Get_SA();Get_Height();Get_ST();return;}int LCP(int l,int r){l=rk[l];r=rk[r];if(l>r) swap(l,r);l++;int z=lg[r-l+1];return min(st[l][z],st[r+1-(1<<z)][z]);} }s1,s2; int main() {scanf("%d",&T);while(T--){memset(a,0,sizeof(a));memset(b,0,sizeof(b));scanf("%s",s1.s+1);n=strlen(s1.s+1);for(int i=1;i<=n;i++)s2.s[n-i+1]=s1.s[i];s1.Build();s2.Build();for(int len=1;len<=n/2;len++){for(int i=len;i<=n;i+=len){int l=i,r=i+len;int L=n-r+2,R=n-l+2;int lcp=min(len,s1.LCP(l,r));int lcs=min(len-1,s2.LCP(L,R));if(lcp+lcs>=len){b[l-lcs]++;b[l+lcp-len+1]--;a[r+lcp]--;a[r-lcs+len-1]++;}}}ans=0;for(int i=1;i<=n;i++){a[i]+=a[i-1],b[i]+=b[i-1];ans+=a[i-1]*b[i];}printf("%lld\n",ans);}return 0; }

    總結

    以上是生活随笔為你收集整理的P1117-[NOI2016]优秀的拆分【SA】的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。