[codeforces616F]Expensive Strings
2016-07-14 20:46
309 查看
题目大意
给出n个字符串以及一个n个元素的c数组。定义一个字符串s的价值为:∑i=1nc[i]∗p[s][i]∗|s| 其中p[s][i]为字符串s在第i个字符串中出现的次数。
求价值最大的字符串的价值。
数据范围
n≤100000 字符串总长≤500000 ci的绝对值不超过107分析
答案肯定是n个字符串中的某一个串的子串。把n个字符串放进后缀自动机里,然后p[s][i]就是s在自动机上跑到一个状态后,该状态right集中r在字符串i里的个数。
加上c[i]的影响,用一个f[x][i]数组来表示状态x的right集中r在字符串i里的个数乘以c[i]。然后每个i的答案都互不影响,所以可以把全部i的答案放在一起统计。
那么变成f[x]=∑sizei=1c[pos[ri]] 其中size为x的right集合大小,pos[ri]表示ri属于哪个字符串。
我们可以先把每个字符串在后缀自动机上跑,给跑到的每个前缀的状态的f都加上c[i]。然后自下而上用每个f[i]更新f[parent[i]]。parent是形成一棵树的,所以随便搞搞。
对于一个状态x,它确定子串的最大长度为max[x],所以ans=max(f[x]∗max[x])
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=1000005,maxm=100005; typedef long long LL; int n,tot,last,e[maxn][26],st[maxm],v[maxm],Parent[maxn],Max[maxn],data[maxn],degree[maxn]; LL ans,f[maxn]; char c,s[maxn]; void add(char c) { int np=++tot,p=last,q,nq; Max[np]=Max[p]+1; for (;p>=0 && !e[p][c-'a'];p=Parent[p]) e[p][c-'a']=np; if (p<0) Parent[np]=0;else { q=e[p][c-'a']; if (Max[q]==Max[p]+1) Parent[np]=q;else { nq=++tot; memcpy(e[nq],e[q],sizeof(e[q])); Parent[nq]=Parent[q]; Max[nq]=Max[p]+1; Parent[np]=Parent[q]=nq; for (;p>=0 && e[p][c-'a']==q;p=Parent[p]) e[p][c-'a']=nq; } } last=np; } int main() { scanf("%d",&n); Parent[0]=-1; for (int i=0;i<n;i++) { for (c=getchar();c<'a' || c>'z';c=getchar()); st[i]=tot; for (;c>='a' && c<='z';c=getchar()) s[tot++]=c; } st =tot; tot=0; for (int i=0;i<n;i++) { scanf("%d",&v[i]); last=0; for (int j=st[i];j<st[i+1];j++) add(s[j]); } for (int i=0;i<n;i++) { int x=0; for (int j=st[i];j<st[i+1];j++) { x=e[x][s[j]-'a']; f[x]+=v[i]; } } for (int i=1;i<=tot;i++) degree[Parent[i]]++; n=tot; tot=0; for (int i=1;i<=n;i++) if (!degree[i]) data[++tot]=i; for (int i=1;i<=tot;i++) { int x=data[i]; ans=max(ans,f[x]*Max[x]); if (!x) break; f[Parent[x]]+=f[x]; degree[Parent[x]]--; if (!degree[Parent[x]]) data[++tot]=Parent[x]; } printf("%I64d\n",ans); return 0; }
相关文章推荐
- Android开发——Accessibility机制实现模拟点击(微信自动抢红包实现)
- NOI2015 程序自动分析
- Spring学习笔记二: Bean装配及生命周期
- Spring学习笔记二: Bean装配及生命周期
- Android开发——Accessibility机制实现模拟点击(微信自动抢红包实现)
- Emacs入门快捷键
- hdu 5682 zxa and leaf
- ThinkPHP 笔记
- Sqlite的使用
- Categorical, Ordinal, Interval - 变量之间的区别
- 详解 SQL 对集合的操作:交、差、并
- vim 实用配置指南
- CentOS7 LNMP环境搭建
- Trie 树(又称字典树,单词查找树)
- 着色
- DLL开发事项
- PHP android ios相互兼容的AES加密算法
- Linux网络编程常用头文件解释
- MIME邮件格式分析及信息提取
- gcc -fPIC编译选项分析