郑厂长系列故事——新闻净化 hdu4534

AC自动机+DP, 此题有俩个优化目标:最少字母使文章符合要求,并让加成分之和尽可能高,可以把俩个目标合并成一个,即让删除一个字母所获得的加分为一个很小的值(此题可以取-200000),这样优化的目标即变为是的加分最大,最后再把结果分离即可。


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>   
#include <map>
#include <string>  
#include <climits> 
#include <set>
#include <string>    
#include <sstream>
#include <utility>   
#include <ctime>

using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::make_pair;
using std::getline;
using std::greater;
using std::endl;
using std::multimap;

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PAIR;
typedef multimap<int, int> MMAP;

const int MAXN(1610);
const int SIGMA_SIZE(26);
const int MAXM(110);
const int MAXE(4000010);
const int MAXH(18);
const int INFI((INT_MAX-1) >> 1);
const int MOD(9999991);
const ULL LIM(1000000000000000ull);

struct AC
{
    int ch[MAXN][SIGMA_SIZE];
    int val[MAXN], f[MAXN], score[MAXN];
    int size;
    
    void init()
    {
        memset(ch[0], 0, sizeof(ch[0]));
        f[0] = val[0] = score[0] = 0;
        size = 1;
    }
    
    inline int idx(char temp)
    {
        return temp-'a';        
    }
    
    void insert(char *S, int tv, int ts)
    {
        int u = 0, id;
        for(; *S; ++S)
        {
            id = idx(*S);
            if(!ch[u][id])
            {
                memset(ch[size], 0, sizeof(ch[size]));
                val[size] = score[size] = 0;
                ch[u][id] = size++;
            }
            u = ch[u][id];
        }
        val[u] |= tv;
        score[u] += ts;
    }
    int que[MAXN];
    int front, back;
    void construct()
    {
        front = back = 0;
        int cur, u;
        for(int i = 0; i < SIGMA_SIZE; ++i)
        {
            u = ch[0][i];
            if(u)
            {
                que[back++] = u;
                f[u] = 0;
            }
        }
        while(front < back)
        {
            cur = que[front++];
            for(int i = 0; i < SIGMA_SIZE; ++i)
            {
                u = ch[cur][i];
                if(u)
                {
                    que[back++] = u;
                    f[u] = ch[f[cur]][i];
                    val[u] |= val[f[u]];
                    score[u] += score[f[u]];
                }
                else
                    ch[cur][i] = ch[f[cur]][i];
            }
        }
    }
};

AC ac;
int table[2][MAXN][1 << 9];
char str[110];

void solve(int len, int m1, int m2)
{
    int cur = 0, last = 1, lim = (1 << m1)-1;
    int forbid = ((1 << m2)-1)^lim;
    for(int i = 0; i < ac.size; ++i)
        for(int j = 0; j <= lim; ++j)
            table[last][i][j] = -INFI;
    table[last][0][0] = 0;
    for(int i = 0; i < len; ++i)
    {
        for(int j = 0; j < ac.size; ++j)
            for(int k = 0; k <= lim; ++k)
                table[cur][j][k] = -INFI;
        for(int j = 0; j < ac.size; ++j)
            for(int k = 0; k <= lim; ++k)
                if(table[last][j][k] != -INFI)
                {
                    table[cur][j][k] = max(table[cur][j][k], table[last][j][k]-200000);
                    int ts = ac.ch[j][ac.idx(str[i])];
                    if((ac.val[ts]&forbid) == 0)
                        table[cur][ts][k|ac.val[ts]] = max(table[cur][ts][k|ac.val[ts]], table[last][j][k]+ac.score[ts]);
                }
        cur ^= 1;
        last ^= 1;
    }
    int ans = -INFI;
    for(int i = 0; i < ac.size; ++i)
        ans = max(ans, table[last][i][lim]);
    if(ans == -INFI)
        printf("Banned\n");
    else
    {
        int a1 = ans/-200000;
        int a2 = ans-a1*-200000;
        if(a2 <= -100000)
            ++a1;
        a2 = ans-a1*-200000;
        printf("%d %d\n", a1, a2);
    }
}

char rec[110][20];
int recv[110];

int main()
{
    int TC, n_case(0);
    scanf("%d", &TC);
    while(TC--)
    {
        ac.init();
        int m1 = 0, m2 = 0;
        int n;
        scanf("%d", &n);
        for(int i = 0; i < n; ++i)
        {
            scanf("%s%d", rec[i], recv+i);
            if(recv[i] == 999)
                ++m1;
        }
        m2 = m1;
        m1 = 0;
        for(int i = 0; i < n; ++i)
        {
            if(recv[i] == 999)
                ac.insert(rec[i], 1 << m1++, 0);
            else
                if(recv[i] == -999)
                    ac.insert(rec[i], 1 << m2++, 0);
                else
                    ac.insert(rec[i], 0, recv[i]);
        }
        ac.construct();
        scanf("%s", str);
        printf("Case %d: ", ++n_case);
        solve(strlen(str), m1, m2);
    }
    return 0;
}


你可能感兴趣的:(郑厂长系列故事——新闻净化 hdu4534)