HDU 2296 Ring (AC自动机+DP)

题目:给出m个模式串,每个串有一定的分值,构造一个长度不超过n的串,使得分值最大,输出长度最小,字典序最小的串

明显的AC+DP,dp[i][j]表示长度为i的时候,在Trie上的第j个结点时的最大分值,path[i][j]表示状态(i,j)时的字典序最小的串。

忘了考虑中间dp相等时还要更新字符串大小

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define L(i) i<<1
#define R(i) i<<1|1
#define INF  0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-9
#define maxn 60010
#define MOD 1000000007

int n,m;
int dp[1110][55];
string ss[1110][55];
int a[110];
char s[110][110];

struct Trie
{
    int next[1110][30],fail[1110],en[1110];
    int root,L;
    void init()
    {
        L = 0;
        root = newnode();
    }
    int newnode()
    {
        for(int i = 0; i < 30; i++)
            next[L][i] = -1;
        en[L++] = 0;
        return L-1;
    }
    void Insert(char buf[],int cnt)
    {
        int now = root;
        int len = strlen(buf);
        for(int i = 0; i < len; i++)
        {
            if(next[now][buf[i]-'a'] == -1)
                next[now][buf[i]-'a'] = newnode();
            now = next[now][buf[i]-'a'];
        }
        en[now] = cnt;
    }
    void build()
    {
        queue Q;
        fail[root] = root;
        for(int i = 0; i < 30; i++)
        {
            if(next[root][i] == -1)
                next[root][i] = root;
            else
            {
                fail[next[root][i]] = root;
                Q.push(next[root][i]);
            }
        }
        while(!Q.empty())
        {
            int now = Q.front();
            Q.pop();
            //en[now] += en[fail[now]];
            for(int i = 0; i < 30; i++)
            {
                if(next[now][i] == -1)
                    next[now][i] = next[fail[now]][i];
                else
                {
                    fail[next[now][i]] = next[fail[now]][i];
                    Q.push(next[now][i]);
                }
            }
        }
    }
    void solve()
    {
        memset(dp,-1,sizeof(dp));
        dp[root][0] = 0;
        ss[root][0] = "";
        for(int i = 0; i <= n; i++)
        {
            for(int j = 0; j < L; j++)
            {
                if(dp[j][i] < 0)
                    continue;
                for(int k = 0; k < 26; k++)
                {
                    if(dp[next[j][k]][i+1] < dp[j][i]+en[next[j][k]])
                    {
                        dp[next[j][k]][i+1] = dp[j][i]+en[next[j][k]];
                        char c = 'a' + k;
                        ss[next[j][k]][i+1] = ss[j][i]+c;
                        //cout< ss[j][i]+c)
                            ss[next[j][k]][i+1] = ss[j][i]+c;
                        //cout< ans)
            {
                ans = dp[i][j];
                sss = ss[i][j];
            }
            else if(dp[i][j] == ans)
                sss = ss[i][j]


你可能感兴趣的:(动态规划,字符串—ac自动机)