BZOJ3676: [Apio2014]回文串

3676: [Apio2014]回文串

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 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的时候顺便找出所有的本质不同的回文字串,并且把每个放到后缀数组里面跑一遍看看出现了多少次。

然后就可以更新答案了。

代码:

 

BZOJ3676: [Apio2014]回文串
  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     else
105     {
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     else
116     {
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 }  
View Code

 

据说也可以hash做?不明觉厉

 

 

BZOJ3676: [Apio2014]回文串

上一篇:安装win8 server core 核心安装


下一篇:C# 以管理员身份运行程序