题目链接:http://codeforces.com/contest/718/problem/E
题目大意:给定一个长度为n的只包含a~h的字符串s,对于1<=a,b<=n,,如果|a-b|=1或s[a]=s[b],就在a与b之间连一条无向边,求这个图的直径以及有多少对点的距离(这里指最短距离)等于这个直径。直径即一个图中距离最大的两个点之间的距离。
数据范围:2<=n<=100 000

题解:设 f [ i ][ c ] 表示从点 i 走到字母为 c 的点的最短距离,这个可以通过枚举 c 然后 bfs 得到,时间复杂度O (n*sigma) 或 O (n*sigma^2) 。对于两个点 i , j ,它们的最短路有两种情况:
1.最短路上只经过相邻点的连边.
2.最短路上有经过同种字母之间的连边.
于是我们可以知道i和j的距离等于min(|i - j| , min(f[i][c]+1+f[j][c]))。

再设dist[c1][c2]为字母为c1和c2的点的最小距离,显然dist[s[i]][c]<=f[i][c]<=dist[s[i]][c]+1,所以我们计算每个点的状态mark[ i ],其中mark[ i ][c]=f[i][c]-dist[s[i]][c],于是我们就可以从点和点的距离(通过mark)变成点和字母的距离啦,至于为什么不是字母和字母的距离,那是因为这样就不能排除情况1的最短路了。

到这里解决方法就差不多出来了,我们从1到n枚举点 i ,然后算出在 i 之前的哪些点与 i 距离属于情况1,这样的点一定是连续的,假设是now~i,然后我们统计1~now-1中的两个值,其中num[x][y]=字母为 x 状态为 z(z包含y,即y&z=y) 的点的个数之和,nums[x]=字母为x的点的个数,时间复杂度O(n*2^sigma)

然后枚举点 i 到字母为 j 的点的距离dst(显然dst=min(f[i][c]+1+dist[c][j]+字母为 j 的点的mark值的第c位))和个数cnt,时间复杂度O(n*sigma^2)
令mindst=min(f[i][c]+1+dist[c][j]),mrk表示状态(其中若f[i][c]+1+dist[c][j]=mindst则mrk[c]=1否则mrk[c]=0),若num[j][mrk]>0那么dst=mindst+1,cnt=num[j][mrk],否则dst=mindst,cnt=nums[j]。然后用dst和cnt更新答案。
最后不要忘了还要判断一下 i 到now的距离。

代码如下:

#include <algorithm>
#include <cstdio>
using namespace std;
const int N=100005;
int d[N],q[N],fi[10],ne[N],f[N][10],dist[10][10],mark[N],num[10][1<<8],nums[10],n;
char s[N];
void bfs(int c){int h=1,t=0,u[10];for (int i=1;i<=n;i++)if (s[i]-'a'==c) d[q[++t]=i]=0;else d[i]=-1;for (int i=0;i<8;i++) u[i]=1;u[c]=0;for (;h<=t;h++){if (u[s[q[h]]-'a']){u[s[q[h]]-'a']=0;for (int i=fi[s[q[h]]-'a'];i;i=ne[i])if (d[i]==-1) d[q[++t]=i]=d[q[h]]+1;}if (q[h]>1 && d[q[h]-1]==-1) d[q[++t]=q[h]-1]=d[q[h]]+1;if (q[h]<n && d[q[h]+1]==-1) d[q[++t]=q[h]+1]=d[q[h]]+1;}for (int i=1;i<=n;i++) f[i][c]=d[i];
}
int main(){scanf("%d\n%s",&n,s+1);for (int i=1;i<=n;i++){ne[i]=fi[s[i]-'a'];fi[s[i]-'a']=i;}for (int i=0;i<8;i++) bfs(i);for (int i=0;i<8;i++)for (int j=0;j<8;j++) dist[i][j]=-1;for (int i=1,j;i<=n;i++)for (j=0;j<8;j++)if (f[i][j]!=-1 && (dist[s[i]-'a'][j]==-1 || f[i][j]<dist[s[i]-'a'][j]))dist[s[i]-'a'][j]=f[i][j];for (int i=1,j;i<=n;i++){mark[i]=0;for (j=7;j>=0;j--) mark[i]=mark[i]<<1^(f[i][j]-dist[s[i]-'a'][j]);}int ans=0,now=1;long long ansp=0;for (int i=1,j,k;i<=n;i++){int l=i;for (;l>=1;l--){int mindst=-1;for (j=0;j<8;j++)if (f[l][j]!=-1 && f[i][j]!=-1 && (mindst==-1 || f[l][j]+f[i][j]+1<mindst))mindst=f[l][j]+f[i][j]+1;if (mindst<=i-l) break;}for (;now<=l;now++){nums[s[now]-'a']++;for (j=mark[now];j;j=(j-1)&mark[now]) num[s[now]-'a'][j]++;}for (j=0;j<8;j++){int mindst=-1,minnum=0;for (k=0;k<8;k++)if (f[i][k]!=-1 && dist[k][j]!=-1 && (mindst==-1 || f[i][k]+dist[k][j]+1<mindst))mindst=f[i][k]+dist[k][j]+1;if (mindst==-1) continue;int mrk=0;for (k=0;k<8;k++)if (f[i][k]!=-1 && dist[k][j]!=-1 && f[i][k]+dist[k][j]+1==mindst) mrk^=1<<k;if (num[j][mrk]) mindst++,minnum=num[j][mrk];else minnum=nums[j];if (!minnum) continue;if (mindst>ans) ans=mindst,ansp=minnum;else if (mindst==ans) ansp=ansp+minnum;}if (i-now>ans) ans=i-now,ansp=1;else if (i-now==ans) ansp++;}printf("%d %I64d\n",ans,ansp);
}

--------------------- 本文来自 aufeas 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/aufeas/article/details/52895953?utm_source=copy

codeforces 718E. Matvey's Birthday相关推荐

  1. Codeforces 718E.Matvey's Birthday dp+状态压缩

    题意 给定一个长度为n的字符串,字符集大小为8.两个点i,j之间有权值为1的边需要满足以下条件至少一个 1. |i-j|=1 2. si=sj 求图的直径和多少个有序点对之间的最短路长度等于直径 N≤ ...

  2. [codeforces 718E]Matvey's Birthday

    题目大意 给定一个长度为n的字符串,字符集大小为8.两个点i,j之间有权值为1的边当且仅当满足以下条件之一 1. |i-j|=1 2. si=sj 求图的直径和多少个有序点对之间的最短路长度等于直径 ...

  3. Codeforces 718E Matvey's Birthday bfs

    题意 给一个长度为n的字符串s,字符集大小为m. 再建立一张n个点的图,其中串中第i个字符就对应图中第i个点. 对这张图连这样两种边: 若对于i,j,满足|i-j|<=1,在点i和点j之间连双向 ...

  4. 【CodeForces】【BFS】【状压】718E Matvey's Birthday

    CodeForces 718E Matvey's Birthday 题目大意 ◇题目传送门◆ 今天与 CF 的连接怎么这么稳定??? 给定一个长度为NNN的字符串sss,字符集为小写字母aaa到hhh ...

  5. 【codeforces 718E】E. Matvey's Birthday

    题目大意&链接: http://codeforces.com/problemset/problem/718/E 给一个长为n(n<=100 000)的只包含'a'~'h'8个字符的字符串 ...

  6. [Codeforces Round #373 DIV1E (CF718E)] Matvey's Birthday

    题意 给定一个字符串,字符集大小为8 将每个位置当做一个点,相邻位置有长度为1的连边,任意相同字母的位置之间有长度为1的连边.求图的直径和直径的长度. n≤105n\le 10^5 题解 求图的直径需 ...

  7. CodeForces 375D Tree and Queries

    传送门:https://codeforces.com/problemset/problem/375/D 题意: 给你一颗有根树,树上每个节点都有其对应的颜色,有m次询问,每次问你以点v为父节点的子树内 ...

  8. 「日常训练」Bad Luck Island(Codeforces Round 301 Div.2 D)

    题意与分析(CodeForces 540D) 是一道概率dp题. 不过我没把它当dp做... 我就是凭着概率的直觉写的,还好这题不算难. 这题的重点在于考虑概率:他们喜相逢的概率是多少?考虑超几何分布 ...

  9. 【codeforces 812C】Sagheer and Nubian Market

    [题目链接]:http://codeforces.com/contest/812/problem/C [题意] 给你n个物品; 你可以选购k个物品;则 每个物品有一个基础价值; 然后还有一个附加价值; ...

最新文章

  1. 人工智能激活千亿级交通安全市场
  2. 形象理解深度学习中八大类型卷积
  3. NSArray排序问题
  4. 北京矿大计算机考研每年分数线,2021中国矿业大学北京考研国家线公布时间_国家线是多少分...
  5. 【2016年第1期】农业大数据研究生培养模式探索
  6. MySQL的五种日期和时间类型
  7. xcode 不值钱的动画UIButton
  8. php 防止access token过期,微信調用接口,防止Access_token過期的方法
  9. _tkinter.TclError: invalid command name “tixComboBox“ 的解决办法
  10. Hello can not find git path
  11. 内蒙古工业大学计算机好调剂吗,内蒙古工业大学信息工程学院2017硕士研究生第三次调剂公告...
  12. 饥荒联机版服务器搭建_Linux 搭建饥荒联机版服务器
  13. spring事务管理tx:Advice详解
  14. linux下mysql(rpm)安装使用手册
  15. 计算机基础教育对工科学生的意义,深入进行高校工科非计算机专业计算机基础教育改革…...
  16. WPS Excel表格日期转文本 为数字问题
  17. 送一个大马给有需要的人,请不要做非法之事
  18. 黑马程序员--Objective-C之--自动释放池的概念以及使用
  19. ​大数据和云计算技术周报(第37期)
  20. 高端对话 | 深度学习能颠覆视频编解码吗

热门文章

  1. php短信接口怎么使用_PHP代码示例_PHP短信接口 | 微米-中国领先的短信彩信接口平台服务商...
  2. 一文详解光电容积图 (PPG) 和心电图 (ECG) 基本工作原理
  3. 新导部队营房室内人员定位系统解决方案
  4. android中的系统应用
  5. android分析内存工具,Android Studio内存泄漏分析工具汇总
  6. 防火墙添加ip白名单_防火墙白名单设置方法firewalld
  7. 漏洞复现篇——利用XSS漏洞实现键盘记录
  8. 北京联通KD-YUN-811E改桥接
  9. ker矩阵是什么意思_矩阵分析(一):空间变换与基变换
  10. javafx控件Button