您的位置:首页 > 其它

hdu2296-(AC自动机+DP)

2017-09-07 18:28 281 查看
题解:将字符串都放在AC自动机上然后看一下到达每个位置能增加多少权值,最后转移的时候跟根据权值大小,字典序大小更新一下即可.dp一维表示长度,二维表示到达哪个结点,一开始把所有的结点初始化成-表示不可能到达该结点dp[0][0]=0。转移方程看下面代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int mx = 1e3+5;
int n,m;
struct node{
char s[55];
int len;
int w;
bool operator<(const node &a)const{
return strcmp(s,a.s)<0;
}
void operator=(const node &a){
for(int i = 0; i < a.len; i++)
s[i] = a.s[i];
len = a.len;
w = a.w;
}
};
struct tried{
int ch[mx][26];
int f[mx];
int v[mx];
node dp[55][mx];
int sz;
void init(){
memset(ch[0],0,sizeof(ch[0]));
memset(dp,0,sizeof(dp));
memset(v,0,sizeof(v));
memset(f,0,sizeof(f));
sz = 1;
}
int idx(char c){
return c-'a';
}
void insert(char *s,int w){
int u = 0;
int len = strlen(s);
for(int i = 0; i < len; i++){
int d = idx(s[i]);
if(!ch[u][d]){
memset(ch[sz],0,sizeof(ch[sz]));
ch[u][d] = sz++;
}
u = ch[u][d];
}
v[u] = w;
}
void getfail(){
queue<int>q;
int u = 0;
for(int d = 0; d < 26; d++)
if(ch[u][d])
q.push(ch[u][d]);
while(!q.empty()){
u = q.front();
q.pop();
v[u]+=v[f[u]];
for(int d = 0; d < 26; d++){
if(!ch[u][d]){
ch[u][d] = ch[f[u]][d];
continue;
}
int ret = ch[u][d];
f[ret] = ch[f[u]][d];
q.push(ret);
}
}
}
void work(){
for(int i = 0; i <= n; i++)
for(int j = 0; j < sz; j++)
dp[i][j].w = -1;
dp[0][0].w = 0;
for(in
4000
t i = 0; i < n; i++)
for(int j = 0; j < sz; j++)
if(dp[i][j].w!=-1)
for(int k = 0; k < 26; k++){
int ret = ch[j][k];
if(dp[i][j].w+v[ret]>dp[i+1][ret].w){
dp[i+1][ret] = dp[i][j];
dp[i+1][ret].s[dp[i+1][ret].len++] = 'a'+k;
dp[i+1][ret].w = dp[i][j].w+v[ret];
}
else if(dp[i][j].w+v[ret]==dp[i+1][ret].w&&dp[i][j]<dp[i+1][ret]){
dp[i+1][ret] = dp[i][j];
dp[i+1][ret].s[dp[i+1][ret].len++] = 'a'+k;
dp[i+1][ret].w = dp[i][j].w+v[ret];
}
}
node ans = dp[0][0];
for(int i = 1; i <= n; i++)
for(int j = 0; j < sz; j++)
if(dp[i][j].w>ans.w)
ans = dp[i][j];
else if(dp[i][j].w==ans.w&&dp[i][j]<ans)
ans = dp[i][j];
ans.s[ans.len] = 0;
puts(ans.s);
}
}word;
char s[mx][20];
int main(){
int t;
scanf("%d",&t);
while(t--){
word.init();
scanf("%d%d",&n,&m);
for(int i = 1; i <= m; i++)
scanf("%s",s[i]);
for(int i = 1; i <= m; i++){
int w;
scanf("%d",&w);
word.insert(s[i],w);
}
word.getfail();
word.work();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: