Gym 101612C Consonant Fencity 建图预处理 + 二进制枚举

题目https://cn.vjudge.net/problem/Gym-101612C

题意:给出一个字符串(长度不超过1e6),仅由小写字母组成。定义一个叫consonant fencity的东西,含义是如果两个连续字母是辅音(本题中辅音指除aeiouwy以外的字母),且大小写不相同,就有一对consonant fencity。题目要求指定每个字母的大小写形式(要求相同字母的大小写形式相同),输出consonant fencity最多的字符串。

思路:显然可以枚举每种字母的大小写形式的组合来求解,但直接枚举再计算的复杂度高达O(n * 2^19),这显然没法接受。考虑到辅音字母是固定的,可以每种辅音字母看作一个结点,将字符串中存在两个字母构成consonant fencity看作有一条从在前的字母到在后的字母的有向边,将这两个字母构成consonant fencity的次数看作边权建图,再用二进制枚举计算时直接扫图即可求解,这样复杂度就降到了O(n)的预处理+19*19*2^19大概1.9e8,对于3秒的时间可以接受。

代码:C++
这里我用bitset进行二进制枚举,当然也可以用位运算

#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
#include <bitset>
#include <cmath>
using namespace std;

const int maxn = 1000000 + 10;
const int maxm = 19;
const char consonants[20] = "bcdfghjklmnpqrstvxz";
int toint[200];

char s[maxn];
int len;

int pic[maxm][maxm];

int maxx = 0;
int maxstatus = 0;

bool isconsonant(char c)
{
    return !(c == 'a' || c == 'e' || c == 'i'|| c == 'o' || c == 'u' || c == 'w' || c == 'y');
}

void init()
{
    for(int i = 0; i < 19; i++)
    {
        toint[consonants[i]] = i;
    }
}

void buildpic()
{
    for(int i = 0; i < len - 1; i++)
    {
        if(isconsonant(s[i]) && isconsonant(s[i+1]))
        {
            pic[toint[s[i]]][toint[s[i+1]]]++;
        }
    }
}

int solve(bitset<32> st)
{
    int ans = 0;
    for(int i = 0; i < maxm; i++)
    {
        for(int j = 0; j < maxm; j++)
        {
            if(pic[i][j] && st[i] ^ st[j])
            {
                ans += pic[i][j];
            }
        }
    }
    return ans;
}

int main()
{
    freopen("consonant.in", "r", stdin);
    freopen("consonant.out", "w", stdout);
    scanf("%s", s);
    len = strlen(s);
    init();
    buildpic();
    int statusnum = 1 << 19;
    for(int i = 0; i < statusnum; i++)
    {
        int t = solve(bitset<32>((unsigned int)i));
        if(t > maxx)
        {
            maxx = t;
            maxstatus = i;
        }
    }
    bitset<32> ans((unsigned)maxstatus);
    for(int i = 0; i < len; i++)
    {
        if(ans[toint[s[i]]])
        {
            putchar(toupper(s[i]));
        }
        else
        {
            putchar(s[i]);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Rewriter_huanying/article/details/81413607