题意:给你一个小写字母字符串,A会把这个序列截断把后半部分补到前半部分之前,形成新的序列,然后告诉你这个新的序列的第一个字母是什么,并且允许你询问一次,这个新序列中任意一个位置的字母是什么,并告诉你答案,问你能否唯一的知道原序列被截断的位置,如果可以,则算你赢,问你赢的最大概率是多少。
思路:我们可以预处理出dp[i][j][k]:字母i和字母j距离为k一共在原序列中出现了几次。统计答案的时候,只需要对于每一个字母i,枚举距离为k的时候,看有几个字母j满足dp[i][j][k]=1,(这个过程等价于,告知你的第一个位置的字母是i,假设你唯一的知道这个原序列被截断的位置为k,那么A告诉你的字母为j的时候是否满足题意),显然对于每一个字母i,找到一个满足dp[i][j][k]的字母j最多的 ,将其累加起来即可。(这个过程等价于,告知你的第一个位置的字母是i,你将选择询问距离为 的那个字母j,这个举动将使你有最大的胜率)
#include <bits/stdc++.h>
using namespace std;
int cnt[26][26][5000 + 5];
int vis[26];
int main()
{
string str;
cin >> str;
for(int i = 0; i < str.size(); i++)
{
vis[str[i] - 'a'] = 1;
for(int dist = 1; dist < str.size(); dist++)
{
cnt[str[i] - 'a'][str[(i + dist) % str.size()] - 'a'][dist]++;
}
}
// puts("?");
double ans = 0;
for(int i = 0; i < 26; i++)
{
int mx = 0;
for(int dist = 1; dist < str.size(); dist++)
{
int temp = 0;
for(int j = 0; j < 26; j++)
{
if(cnt[i][j][dist] == 1) temp++;
}
mx = max(mx, temp);
}
ans += 1.0 * mx / str.size();
}
printf("%.8f\n", ans);
return 0;