hdu 3948(后缀数组+RMQ)
生活随笔
收集整理的這篇文章主要介紹了
hdu 3948(后缀数组+RMQ)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題意:求一個串中有多少不同的回文串。
分析:這一題的關(guān)鍵是如何去重,我表示我現(xiàn)在還沒理解為什么這樣去重,先放這里過兩天再看!!
//不同回文子串數(shù)目 #include <iostream> #include <string> #include <cmath> #include <map> using namespace std; #define N 200010 int ws1[N],wv[N],wa[N],wb[N]; int rank1[N],height[N],sa[N]; char str[N]; int a[N],n; int dp[N][25],vis[N];int mmin(int a,int b) {return a>b?b:a; }int cmp(int *r,int a,int b,int l) {return r[a]==r[b] && r[a+l]==r[b+l]; }void da(int *r,int *sa,int n,int m) {int i,j,p,*x=wa,*y=wb,*t;for(i=0;i<m;i++)ws1[i]=0;for(i=0;i<n;i++)ws1[x[i]=r[i]]++;for(i=1;i<m;i++)ws1[i]+=ws1[i-1];for(i=n-1;i>=0;i--)sa[--ws1[x[i]]]=i;for(j=1,p=1;p<n;j*=2,m=p){for(p=0,i=n-j;i<n;i++)y[p++]=i;for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;for(i=0;i<n;i++)wv[i]=x[y[i]];for(i=0;i<m;i++)ws1[i]=0;for(i=0;i<n;i++)ws1[wv[i]]++;for(i=1;i<m;i++)ws1[i]+=ws1[i-1];for(i=n-1;i>=0;i--)sa[--ws1[wv[i]]]=y[i];for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;} }void calheight(int *r,int *sa,int n) {int i,j,k=0;for(i=1;i<=n;i++)rank1[sa[i]]=i;for(i=0;i<n;height[rank1[i++]]=k)for(k?k--:0,j=sa[rank1[i]-1];r[i+k]==r[j+k];k++) ; }void RMQ(int n)//RMQ預(yù)處理 {int i,j;memset(dp,127,sizeof(dp));for(i=1;i<=n;i++)dp[i][0]=height[i];for(j=1;(1<<j)<=n;j++)for(i=1;i+(1<<j)-1<=n;i++)dp[i][j]=mmin(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); }int lcp(int l,int r)//求最長公共前綴 {int a=rank1[l],b=rank1[r];if(a>b)swap(a,b);a++;int t=(int)(log(double(b-a+1))/log(2.00));return mmin(dp[a][t],dp[b-(1<<t)+1][t]); }int main() {int T,i,k,ca=0,s,t,ans;scanf("%d",&T);while(T--){scanf("%s",str);k=strlen(str);str[k]='9';for(i=0;i<k;i++)str[i+k+1]=str[k-i-1];str[2*k+1]='0';n=2*k+2;str[n]='\0';for(i=0;i<n;i++) a[i]=(int)str[i]; da(a,sa,n,'z'+1);calheight(a,sa,n-1);RMQ(n-1);ans=0;memset(vis,0,sizeof(vis));s=0;for(i=2;i<n;i++)//奇數(shù)的時候 {s=mmin(s,height[i]);if(vis[2*k-sa[i]]){t=lcp(sa[i],2*k-sa[i]);if(t>s){ans+=t-s;s=t;}}elsevis[sa[i]]=1;}memset(vis,0,sizeof(vis));s=0;for(i=2;i<n;i++)//偶數(shù)的時候 {s=mmin(s,height[i]);if(!sa[i])continue;if(vis[2*k-sa[i]+1]){t=lcp(sa[i],2*k-sa[i]+1);if(t>s){ans+=t-s;s=t;}}elsevis[sa[i]]=1;}printf("Case #%d: %d\n",++ca,ans);}return 0; }?
轉(zhuǎn)載于:https://www.cnblogs.com/jiangjing/p/3250981.html
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的hdu 3948(后缀数组+RMQ)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python中的threading_Py
- 下一篇: arm vic