版权声明:沃斯里德小浩浩啊 https://blog.csdn.net/Healer66/article/details/82795920
链接:
https://odzkskevi.qnssl.com/76ee6a37a5e7b6e0a1da0f46372ab4da?v=1537373000
题意:
把26个字母分成19个辅音字母和7个元音字母,让你通过改变辅音字母的大小写状态,使得字符串中连续的两个大小写状态不同的辅音字母组成的字母对数量最多,输出该状态下的字符串。
扫一遍字符串,统计每种辅音字母对的数量,总共19*19种。
枚举19个辅音字母的大小写状态(二进制状压),内循环枚举每两个辅音字母的前后关系,维护一个最大值
((t>>i)^(t>>j))&1意思是第i位和第j位不相等(一个是0,一个是1),相当于一个大写一个小写
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5;
char f[20]= {'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'x', 'z'};
int a[30][30],v[30][30],vis[300];
char s[N];
int main()
{
int i,j,k;
//freopen("consonant.in","r",stdin);
// freopen("consonant.out","w",stdout);
scanf("%s",s);
for(i=0; s[i+1]; i++)
{
a[s[i]-'a'][s[i+1]-'a']++;//记录相邻辅音数量
}
for(i=0; i<19; i++)
{
for(j=0; j<19; j++)
{
v[i][j]=a[f[i]-'a'][f[j]-'a'];
}
}
int maxx=0,flag=0;
for(int t=0; t<(1<<19); t++) //枚举状态,二进制的每一位表示是否大写
{
int sum=0,ss=0;
for(i=0; i<19; i++) //枚举前面的辅音字母
{
for(j=0; j<19; j++)//枚举后面的辅音字母
{
if(((t>>i)^(t>>j))&1)//如果两字母大小写不同
{
sum+=v[i][j];
}
}
}
if(sum>maxx) //记录最大值maxx和该状态t
{
maxx=sum;
flag=t;
}
}
for(i=0; i<19; i++)
{
if(flag&(1<<i)) //记录最大状态下需要大写的字母。
{
vis[f[i]]=1;
}
}
for(i=0; s[i]; i++)
{
if(vis[s[i]])
printf("%c",s[i]-32);
else
printf("%c",s[i]);
}
puts("");
}