Ring - HDU 2296(自动机+dp)

时间:2021-12-13 23:57:52
题目大意:斯蒂文想送给他女盆友一个戒指,并且他想在戒指上刻一些字,他非常了解他女盆友喜欢什么单词,比如"love""forvevr"....并且他还把女盆友喜欢的单词弄了一个高兴度,他现在准备在这个戒指上刻上一个长度不超过N的句子,并且这个句子的高兴度是最大的,如果有多个这样的句子,选择最短的,如果还有多个选择字典序最小的。
 
分析:比较容易想到DP来做,定义数组dp[Ni][kNode],保存第i长度到达k节点的最大价值,然后再用一个数组来保存路径就行了,注意dp数组初始化的时候应该初始化成一个很小的值...在这wa了好多次......................
 
代码如下:
======================================================================================================================================
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std; const int MAXN = ;
const int MAXM = ;
const int MaxSon = ;
const int oo = 1e9+; int dp[MAXM][MAXN];
char path[MAXM][MAXN][MAXM]; struct Ac_Trie
{
int next[MAXN][MaxSon];
int Fail[MAXN], End[MAXN];
int cnt, root; int newnode()
{
for(int i=; i<MaxSon; i++)
next[cnt][i] = -;
Fail[cnt] = End[cnt] = false; return cnt++;
}
void InIt()
{
cnt = ;
root = newnode();
} void Insert(char s[], int val)
{
int now = root; for(int i=; s[i]; i++)
{
int k = s[i]-'a'; if(next[now][k] == -)
next[now][k] = newnode();
now = next[now][k];
} End[now] = val;
}
void GetFial()
{
queue<int>Q;
int now = root; for(int i=; i<MaxSon; i++)
{
if(next[now][i] == -)
next[now][i] = root;
else
{
Fail[next[now][i]] = root;
Q.push(next[now][i]);
}
} while(Q.size())
{
now = Q.front();
Q.pop(); for(int i=; i<MaxSon; i++)
{
if(next[now][i] == -)
next[now][i] = next[Fail[now]][i];
else
{
Fail[next[now][i]] = next[Fail[now]][i];
Q.push(next[now][i]);
}
}
}
}
};
Ac_Trie ac; bool cmp(char a[], char b[])
{
int len_a = strlen(a);
int len_b = strlen(b); if(len_a != len_b)
return len_a > len_b;
return strcmp(a, b) > ;
} int main()
{
int T; scanf("%d", &T); while(T--)
{
int i, j, k, N, M, val;
char s[][];
ac.InIt(); scanf("%d%d", &N, &M); for(i=; i<M; i++)
scanf("%s", s[i]); for(i=; i<M; i++)
{
scanf("%d", &val);
ac.Insert(s[i], val);
} ac.GetFial(); for(i=; i<=N; i++)
for(j=; j<ac.cnt; j++)
dp[i][j] = -oo; memset(path, false, sizeof(path)); char ans[MAXM] = {};
int Max = ;
dp[][] = ; for(i=; i<N; i++)
for(j=; j<ac.cnt; j++)
{
char temp[] = {};
strcpy(temp, path[i][j]);
int len = strlen(temp); for(k=; k<MaxSon; k++)
{
int next = ac.next[j][k];
temp[len] = k+'a'; val = dp[i][j]+ac.End[next]; if(dp[i+][next] < val || (dp[i+][next]==val && cmp(path[i+][next], temp) ) )
{
dp[i+][next] = val;
strcpy(path[i+][next], temp); if(Max < val || (Max==val && cmp(ans, temp)))
{
Max = val;
strcpy(ans, temp);
}
}
}
}
printf("%s\n", ans);
} return ;
}