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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

[bzoj4566][HAOI2016]找相同字符

發布時間:2024/1/18 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [bzoj4566][HAOI2016]找相同字符 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

4566: [Haoi2016]找相同字符

Time Limit: 20 Sec Memory Limit: 256 MB
Submit: 113 Solved: 64
[Submit][Status][Discuss]
Description

給定兩個字符串,求出在兩個字符串中各取出一個子串使得這兩個子串相同的方案數。兩個方案不同當且僅當這兩
個子串中有一個位置不同。
Input

兩行,兩個字符串s1,s2,長度分別為n1,n2。1 <=n1, n2<= 200000,字符串中只有小寫字母

Output

輸出一個整數表示答案

Sample Input

aabb

bbaa
Sample Output

10

把兩個串用一個很大的字符連接起來,求一個后綴數組。
考慮怎樣暴力的算答案。
rank 數組中從前往后枚舉起點,對于每個枚舉的起點,都暴力的往后掃,掃的過程中維護一個 height 的最小值。每到一個點的時候,如果這個點跟起點不屬于一個串,就將答案加上當前的最小值,這樣是 O(n2) 的(注釋的代碼就是。。)
考慮這個還能怎么算。可以發現我們是維護 height 的最小值。那么我們可以按照 height 從大到小的順序掃,這樣每次需要用的就是當前的 height
掃的過程中用并查集維護一下每個串分別對哪些串有貢獻的(也就是 height 數組的貢獻)。
用乘法原理算一下當前的 height 會有多少貢獻。就是用當前的 height 乘上這個串和上一個串分別對于兩個兩個不同的原串的乘積的和。

#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define LL long long const int N=400010; LL ans; char ss[N]; int n,m,len[2],sa[N],c[N],rank[N],height[N],t1[N],t2[N],s[N],fa[N],st[N],en[N],a[N]; inline bool cmp(int *y,int p,int q,int k){int o0=p+k>=n?-1:y[p+k];int o1=q+k>=n?-1:y[q+k];return o0==o1&&y[p]==y[q]; } inline void build_sa(){int i,k,p,*x=t1,*y=t2;for(m=28,i=0;i<m;++i) c[i]=0;for(i=0;i<n;++i) ++c[x[i]=s[i]];for(i=1;i<m;++i) c[i]+=c[i-1];for(i=n-1;~i;--i) sa[--c[x[i]]]=i;for(k=1;k<=n;k<<=1){for(p=0,i=n-k;i<n;++i) y[p++]=i;for(i=0;i<n;++i) if(sa[i]>=k) y[p++]=sa[i]-k;for(i=0;i<m;++i) c[i]=0;for(i=0;i<n;++i) ++c[x[y[i]]];for(i=1;i<m;++i) c[i]+=c[i-1];for(i=n-1;~i;--i) sa[--c[x[y[i]]]]=y[i];swap(x,y);m=1;x[sa[0]]=0;for(i=1;i<n;++i) x[sa[i]]=cmp(y,sa[i],sa[i-1],k)?m-1:m++;if(m>=n) break;} } inline void build_height(){int i,k=0,j;for(i=0;i<n;++i) rank[sa[i]]=i;for(i=0;i<n;++i){if(!rank[i]) continue;k=k?--k:k;j=sa[rank[i]-1];while(s[i+k]==s[j+k]) ++k;height[rank[i]]=k;} } inline bool CMP(int x,int y){return height[x]>height[y]; } inline int find(int x){if(x!=fa[x]) fa[x]=find(fa[x]);return fa[x]; } inline void calc(int x){if(!x) return ;int r1=find(x),r2=find(x-1);ans+=(LL)(st[r1]*en[r2]+st[r2]*en[r1])*(LL)height[x];st[r1]+=st[r2];en[r1]+=en[r2];fa[r2]=r1; } int main(){int i,j,minn;scanf("%s",ss);len[0]=strlen(ss);for(i=0;i<len[0];++i) s[i]=ss[i]-'a'+1;scanf("%s",ss);len[1]=strlen(ss);for(s[len[0]]=27,i=0;i<len[1];++i) s[i+len[0]+1]=ss[i]-'a'+1;n=len[0]+len[1]+1;build_sa();build_height(); /* for(i=0;i<n;++i){int now=(sa[i]<len[0]);for(minn=n+1,j=i+1;j<n;++j){minn=min(minn,height[j]);if(minn==0) break;if((sa[j]>len[0])==now){//cout<<i<<' '<<j<<' '<<minn<<endl;ans+=(LL)minn;}}}*/for(i=0;i<n;++i){a[i]=fa[i]=i;st[i]=(sa[i]<len[0]);en[i]=1-st[i];}sort(a,a+n,CMP);for(i=0;i<n;++i) calc(a[i]);printf("%lld\n",ans); }

總結

以上是生活随笔為你收集整理的[bzoj4566][HAOI2016]找相同字符的全部內容,希望文章能夠幫你解決所遇到的問題。

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