首页 > 代码库 > BZOJ3676: [Apio2014]回文串
BZOJ3676: [Apio2014]回文串
3676: [Apio2014]回文串
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 211 Solved: 51
[Submit][Status]
Description
考虑一个只包含小写拉丁字母的字符串s。我们定义s的一个子串t的“出
现值”为t在s中的出现次数乘以t的长度。请你求出s的所有回文子串中的最
大出现值。
Input
输入只有一行,为一个只包含小写字母(a -z)的非空字符串s。
Output
输出一个整数,为逝查回文子串的最大出现值。
【数据规模与评分】
数据满足1≤字符串长度≤300000。
题解:
总算A了这题,感觉好舒畅。。。
首先我们要知道一个结论:
只有使mx变大的回文串,才是与之前所有回文子串不同的新串,否则一定可以由之前的回文串关于id对称得到
所以本质不同的回文子串数量是O(N)级别的
因为我们不能把所有找到的回文串都去跑一遍。。。
所以我们manacher的时候顺便找出所有的本质不同的回文字串,并且把每个放到后缀数组里面跑一遍看看出现了多少次。
然后就可以更新答案了。
代码:
1 #include<cstdio> 2 3 #include<cstdlib> 4 5 #include<cmath> 6 7 #include<cstring> 8 9 #include<algorithm> 10 11 #include<iostream> 12 13 #include<vector> 14 15 #include<map> 16 17 #include<set> 18 19 #include<queue> 20 21 #include<string> 22 23 #define inf 1000000000 24 25 #define maxn 650000+5 26 27 #define maxm 20000000+5 28 29 #define eps 1e-10 30 31 #define ll long long 32 33 #define pa pair<int,int> 34 35 #define for0(i,n) for(int i=0;i<=(n);i++) 36 37 #define for1(i,n) for(int i=1;i<=(n);i++) 38 39 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 40 41 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 42 43 #define mod 1000000007 44 45 using namespace std; 46 47 inline int read() 48 49 { 50 51 int x=0,f=1;char ch=getchar(); 52 53 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} 54 55 while(ch>=‘0‘&&ch<=‘9‘){x=10*x+ch-‘0‘;ch=getchar();} 56 57 return x*f; 58 59 } 60 int n,m; 61 int t1[maxn],t2[maxn],c[maxn],a[maxn],sa[maxn],rk[maxn],h[maxn],st[maxn][20]; 62 int b[maxn],p[maxn]; 63 char s[maxn]; 64 void getsa(int m) 65 { 66 int *x=t1,*y=t2; 67 for0(i,m)c[i]=0; 68 for0(i,n)c[x[i]=a[i]]++; 69 for1(i,m)c[i]+=c[i-1]; 70 for3(i,n,0)sa[--c[x[i]]]=i; 71 for(int k=1;k<=n+1;k<<=1) 72 { 73 int p=0; 74 for2(i,n-k+1,n)y[p++]=i; 75 for0(i,n)if(sa[i]>=k)y[p++]=sa[i]-k; 76 for0(i,m)c[i]=0; 77 for0(i,n)c[x[y[i]]]++; 78 for1(i,m)c[i]+=c[i-1]; 79 for3(i,n,0)sa[--c[x[y[i]]]]=y[i]; 80 swap(x,y);p=0;x[sa[0]]=0; 81 for1(i,n)x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p:++p; 82 if(p>=n)break; 83 m=p; 84 } 85 for1(i,n)rk[sa[i]]=i; 86 for(int i=0,k=0,j;i<n;h[rk[i++]]=k) 87 for(k?k--:0,j=sa[rk[i]-1];a[i+k]==a[j+k];k++); 88 } 89 void getst() 90 { 91 int k=log2(n); 92 for1(i,n)st[i][0]=h[i]; 93 for1(j,k)for1(i,n-(1<<j)+1)st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]); 94 } 95 inline int rmq(int x,int y) 96 { 97 int k=log2(y-x+1); 98 return min(st[x][k],st[y-(1<<k)+1][k]); 99 }100 inline ll query(int x,int y)101 {102 int l,r,mid,ql,qr;103 if(h[x+1]<y)qr=x;104 else105 {106 l=x+1;r=n;107 while(l<=r)108 {109 mid=(l+r)>>1;110 if(rmq(x+1,mid)>=y)l=mid+1;else r=mid-1;111 }112 qr=r;113 }114 if(h[x]<y)ql=x;115 else116 {117 l=1;r=x-1;118 while(l<=r)119 {120 mid=(l+r)>>1;121 //cout<<l<<‘ ‘<<mid<<‘ ‘<<r<<endl;122 if(rmq(mid+1,x)>=y)r=mid-1;else l=mid+1;123 }124 ql=l;125 }126 //cout<<x<<‘ ‘<<y<<‘ ‘<<ql<<‘ ‘<<qr<<endl;127 /*for2(i,sa[x],sa[x]+y-1)cout<<s[i];128 cout<<‘ ‘<<ql<<‘ ‘<<qr<<endl;*/129 return (ll)(qr-ql+1)*(ll)y;130 }131 132 int main()133 134 {135 136 freopen("input.txt","r",stdin);137 138 freopen("output.txt","w",stdout);139 140 scanf("%s",s);n=strlen(s);141 for0(i,n-1)a[i]=s[i]-‘a‘+1;a[n]=0;142 getsa(26);getst();143 for0(i,n-1)b[(i+1)<<1]=a[i];144 m=(n<<1)+1;145 int id=0,mx=0;ll ans=0;146 for1(i,m)147 {148 if(mx>i)p[i]=min(p[2*id-i],mx-i);149 while(i-p[i]-1>0&&i+p[i]+1<=m&&b[i-p[i]-1]==b[i+p[i]+1])p[i]++;150 if(i+p[i]>mx)151 {152 mx=i+p[i];153 id=i;154 ans=max(ans,query(rk[(i-p[i]-1)>>1],p[i]));155 //cout<<i<<‘ ‘<<p[i]<<‘ ‘<<(i-p[i]-1>>1)<<‘ ‘<<(rk[(i-p[i]-1)>>1])<<endl;156 }157 }158 //for1(i,m)cout<<i<<‘ ‘<<b[i]<<‘ ‘<<p[i]<<endl;159 printf("%lld\n",ans);160 161 return 0;162 163 }
据说也可以hash做?不明觉厉
BZOJ3676: [Apio2014]回文串
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。