hdu3948(后缀数组)
题意:给一串字符,需要你求不相同的回文子串个数.......
同ural1297,链接:http://www.cnblogs.com/ziyi--caolu/archive/2013/06/09/3129877.html
#include<iostream> #include<stdio.h> #include<string.h> using namespace std; #define maxn 210000 #define max(x,y) x>y? x:y #define min(x,y) x>y? y:x int dp[maxn][32],log2[maxn]; int wa[maxn],wb[maxn],wsf[maxn],wv[maxn],sa[maxn]; int rank[maxn],height[maxn],s[maxn]; char str[maxn]; int cmp(int *r,int a,int b,int k) { return r[a]==r[b]&&r[a+k]==r[b+k]; } void getsa(int *r,int *sa,int n,int m) { int i,j,p,*x=wa,*y=wb,*t; for(i=0;i<m;i++) wsf[i]=0; for(i=0;i<n;i++) wsf[x[i]=r[i]]++; for(i=1;i<m;i++) wsf[i]+=wsf[i-1]; for(i=n-1;i>=0;i--) sa[--wsf[x[i]]]=i; p=1; j=1; for(;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++) wsf[i]=0; for(i=0;i<n;i++) wsf[wv[i]]++; for(i=1;i<m;i++) wsf[i]+=wsf[i-1]; for(i=n-1;i>=0;i--) sa[--wsf[wv[i]]]=y[i]; t=x; x=y; y=t; x[sa[0]]=0; for(p=1,i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)? p-1:p++; } } void getheight(int *r,int n) { int i,j,k=0; for(i=1;i<=n;i++) rank[sa[i]]=i; for(i=0;i<n;i++) { if(k) k--; else k=0; j=sa[rank[i]-1]; while(r[i+k]==r[j+k]) k++; height[rank[i]]=k; } } void rmq_init(int n) { for(int i=1;i<=n;i++) dp[i][0]=height[i]; for(int j=1;(1<<j)<=n;j++) for(int i=1;i+(1<<j)-1<=n;i++) dp[i][j]=dp[i][j-1]<dp[i+(1<<(j-1))][j-1]? dp[i][j-1]:dp[i+(1<<(j-1))][j-1]; } int rmq(int left,int right) { int k=log2[right-left+1]; //printf(":%d %d %d\n",k,left,right); return min(dp[left][k],dp[right-(1<<k)+1][k]); } int main() { int text,xxx=0; scanf("%d",&text); int num = 0, tot = 1; while(tot < maxn) { for(int i = tot; i < tot * 2 && i < maxn; ++i) log2[i] = num; num++; tot *= 2; } while(text--) { scanf("%s",str); int len=strlen(str),j=0; for(int i=0;i<len;i++) { s[j++]=str[i]-'a'+1; } s[j++]=29; for(int i=len-1;i>=0;i--) { s[j++]=str[i]-'a'+1; } s[j]=0; int len1=j; getsa(s,sa,len1+1,32); getheight(s,len1); rmq_init(len1); int sum=0; int cnt=0; for(int i=1;i<len1;i++) { cnt=cnt>height[i] ? height[i]:cnt; if(sa[i]<len) { int tmp=2*len-sa[i]; int pp,qq; if(i<rank[tmp]) pp=i; else pp=rank[tmp]; if(i>rank[tmp]) qq=i; else qq=rank[tmp]; //int pp=min(i,rank[tmp]); int k=rmq(pp+1,qq); //printf("%d %d\n",i,rank[tmp]); //printf("%d %d %d\n",pp+1,qq,tmp); //printf("1:%d %d %d\n",i,rank[tmp],k); if(k>cnt) { sum+=k-cnt; cnt=k; } } } cnt=0; //printf("\n\n"); for(int i=1;i<len1;i++) { cnt= (cnt>height[i]) ? height[i] : cnt; if(!sa[i]) continue; if(sa[i]<len) { int tmp=2*len-sa[i]+1; int pp,qq; if(i<rank[tmp]) pp=i; else pp=rank[tmp]; if(i>rank[tmp]) qq=i; else qq=rank[tmp]; int k=rmq(pp+1,qq); printf("%d %d\n",pp+1,qq); //printf("%d %d\n",min(i,rank[tmp])+1,max(i,rank[tmp])); //printf("2:%d %d %d\n",i,rank[tmp],k); if(k>cnt) { sum+=k-cnt; cnt=k; } } } //printf("Case #%d: %d\n",++xxx,sum); } return 0; }
朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。