【APIO2014】UOJ103 Palindromes【解法一】
来源:互联网 发布:Apache cxf wsdl 编辑:程序博客网 时间:2024/06/07 02:41
给你一个由小写拉丁字母组成的字符串 ss。我们定义 ss 的一个子串的存在值为这个子串在 ss 中出现的次数乘以这个子串的长度。
对于给你的这个字符串 ss,求所有回文子串中的最大存在值。
输入格式 一行,一个由小写拉丁字母(a~z)组成的非空字符串 ss。
输出格式 输出一个整数,表示所有回文子串中的最大存在值。
解法二【manacher+SAM】见【这里】。
解法三【pam】见【这里】。
用manacher找出所有本质不同的字符串【O(n)个】,然后在后缀数组上查询出现次数。复杂度O(nlogn)。
注意manacher当更新mx时,答案不一定是当前的极大值。所有比mx大的位置都要检查更新答案,比如说uoj上的hack数据
cacbabdadeaefafgaghahjaj
答案应该是8而不是3。
在bzoj上过不了,在uoj上卡过了。
#include<cstdio>#include<cstring>#define LL long longchar s[600010],ss[600010];int sa[600010],rank[600010],height[600010],cnt[600010],t1[600010],t2[600010],n,mn[600010][22],mx[600010][22],f[600010],kk[600010];int min(int x,int y){ return x<y?x:y;}LL max(LL x,LL y){ return x>y?x:y;}void init(){ int i,tem=0; char c=getchar(); while (c>='a'&&c<='z') { ss[++tem]=c; c=getchar(); } n=2*tem+1; for (i=1;i<=n;i++) if (i&1) s[i]='$'; else s[i]=ss[i/2];}void make_sa(){ int i,j,k,p,m='z',*x=t1,*y=t2,*z; for (i=1;i<=n;i++) cnt[x[i]=s[i]]++; for (i=2;i<=m;i++) cnt[i]+=cnt[i-1]; for (i=n;i;i--) sa[cnt[x[i]]--]=i; for (k=1;k<=n;k<<=1) { p=0; for (i=n-k+1;i<=n;i++) y[++p]=i; for (i=1;i<=n;i++) if (sa[i]-k>=1) y[++p]=sa[i]-k; for (i=1;i<=m;i++) cnt[i]=0; for (i=1;i<=n;i++) cnt[x[y[i]]]++; for (i=2;i<=m;i++) cnt[i]+=cnt[i-1]; for (i=n;i;i--) sa[cnt[x[y[i]]]--]=y[i]; z=x; x=y; y=z; p=x[sa[1]]=1; for (i=2;i<=n;i++) { if (y[sa[i]]!=y[sa[i-1]]||y[sa[i]+k]!=y[sa[i-1]+k]) p++; x[sa[i]]=p; } if ((m=p)>=n) break; } for (i=1;i<=n;i++) rank[sa[i]]=i; for (i=1,k=0;i<=n;i++) { if (k) k--; if (rank[i]==1) continue; while (s[i+k]==s[sa[rank[i]-1]+k]) k++; height[rank[i]]=k; } for (i=1;i<=n;i++) mn[i][0]=height[i]; for (k=1;(1<<k)<=n;k++) for (i=1;i+(1<<k)-1<=n;i++) mn[i][k]=min(mn[i][k-1],mn[i+(1<<k-1)][k-1]); kk[0]=-1; for (i=1;i<=n;i++) kk[i]=(i&i-1)?kk[i-1]:kk[i-1]+1;}int get(int x,int y){ if (x==y) return n-sa[x]+1; x++; int k=kk[y-x+1]; return min(mn[x][k],mn[y-(1<<k)+1][k]);}int qry(int p,int l){ int ll,rr,mid,ret=0; ll=1; rr=p; while (ll<rr) { mid=(ll+rr)/2; if (get(mid,p)>=l) rr=mid; else ll=mid+1; } ret+=p-ll+1; ll=p; rr=n; while (ll<rr) { mid=(ll+rr+1)/2; if (get(p,mid)>=l) ll=mid; else rr=mid-1; } return ret+ll-p;}LL solve(){ int mx=0,id=0,i,j,k,x; LL ans=0; for (i=1;i<=n;i++) { if (mx>=i) f[i]=min(mx-i,f[2*id-i]); else f[i]=0; while (i-f[i]-1>=1&&i+f[i]+1<=n&&s[i+f[i]+1]==s[i-f[i]-1]) f[i]++; if (i+f[i]>mx) { for (x=mx-i+2;x<=f[i];x+=2) ans=max(ans,(LL)qry(rank[i-x],2*x+1)*x); mx=i+f[i]; id=i; } } return ans;}int main(){ init(); make_sa(); printf("%lld\n",solve());}
0 0
- 【APIO2014】UOJ103 Palindromes【解法一】
- 【APIO2014】【UOJ103】【BZOJ3676】 Palindromes 题意&代码(C++)
- 【APIO2014】Palindromes
- 【APIO2014】bzoj3676 回文串【解法二】
- 【APIO2014】bzoj3676 回文串【解法三】
- [bzoj 3676][uoj #103]【APIO2014】Palindromes回文串 后缀数组+manachar
- Palindromes
- Palindromes
- Palindromes
- Palindromes
- Palindromes
- Palindromes
- Palindromes
- Palindromes
- Palindromes
- Palindromes
- Palindromes
- Palindromes
- hexdump命令
- 线段树
- SDR技术原理解析 USRP收发原理
- 编程实现对输入的字符串进行逆序
- FJNU 1200 PY 思维题
- 【APIO2014】UOJ103 Palindromes【解法一】
- 作业2:计数器数码管显示
- Java 创建文件夹及文件
- 商城开发计划(1)
- 迷宫问题
- Linux下/proc目录简介
- 判断屏幕是在什么模式下
- 微信支付之统一下单
- 创建maven工程(spring-springmvc-mybatis三大框架整合)