您的位置:首页 > 其它

HDU 2296 Ring

2016-05-19 21:14 405 查看
给定m个模式串和对应的权值,求长度为n的包含总权值最大的目标串,如果有多个解输出最短的个,如果还有多个解输出字典序最小的个。end数组记录权值后用dp来跑,字符串处理会麻烦些,代码如下

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
const int INF=1e9;
const int MOD=20090717;

int a[110];
int dp[55][1200];
char str[55][1200][55];
char ans[55];
struct Tree
{
int next[1200][26],end[1200],fail[1200];
int L,root;
int newnode()
{
for(int i=0;i<26;i++)
{
next[L][i]=-1;
}
end[L++]=-1;
return L-1;
}
void init()
{
L=0;
root=newnode();
}
void insert(char *s,int idx)
{
int len=strlen(s);
int p=root;
for(int i=0;i<len;i++)
{
int id=s[i]-'a';
if(next[p][id]==-1)
{
next[p][id]=newnode();
}
p=next[p][id];
}
end[p]=idx;
}
void build()
{
queue<int>q;
int p=root;
fail[root]=root;
for(int i=0;i<26;i++)
{
if(next[p][i]==-1)
{
next[p][i]=root;
}
else
{
fail[next[p][i]]=root;
q.push(next[p][i]);
}
}
while(!q.empty())
{
p=q.front();
q.pop();
for(int i=0;i<26;i++)
{
if(next[p][i]==-1)
{
next[p][i]=next[fail[p]][i];
}
else
{
fail[next[p][i]]=next[fail[p]][i];
q.push(next[p][i]);
}
}
}
}
void query(char *s)
{
int len=strlen(s);
int p=root,ans=0;
for(int i=0;i<len;i++)
{
int id=s[i]-'a';
p=next[p][id];
int temp=p;
while(temp!=root)
{
if(end[temp])
{
ans+=end[temp];
end[temp]=0;
}
temp=fail[temp];
}
}
}
void debug()
{
for(int i = 0;i < L;i++)
{
printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],end[i]);
for(int j = 0;j < 26;j++)
printf("%2d",next[i][j]);
printf("]\n");
}
}
bool cmp(char *a,char *b)
{
int len1=strlen(a);
int len2=strlen(b);
if(len1==len2) return strcmp(a,b)<0;
else return len1<len2;
}
void solve(int n)
{
strcpy(str[0][0],"");
strcpy(ans,"");
for(int i=0;i<=n;i++)
{
for(int j=0;j<L;j++)
dp[i][j]=-INF;
}
dp[0][0]=0;
int Max=0;
char tmp[55];
for(int i=0;i<n;i++)
{
for(int j=0;j<L;j++)
{
int len=strlen(str[i][j]);
strcpy(tmp,str[i][j]);
//	printf("!%d %d %d %s\n",i,j,dp[i][j],tmp);
for(int k=0;k<26;k++)
{
int nextj=next[j][k];
int num=dp[i][j];
tmp[len]='a'+k;
tmp[len+1]=0;
if(end[nextj]!=-1) num+=a[end[nextj]];
if(dp[i+1][nextj]<num||(dp[i+1][nextj]==num&&cmp(tmp,str[i+1][nextj])))
{
//	printf("%d %d %d %d %s %s %s\n",k,dp[i+1][nextj],num,Max,tmp,str[i+1][nextj],ans);
dp[i+1][nextj]=num;
strcpy(str[i+1][nextj],tmp);
if(num>Max||(num==Max&&cmp(tmp,ans)))
{
Max=num;
strcpy(ans,tmp);
}
}
}
}
}
printf("%s\n",ans);
}
};
Tree ac;
char s[22];

int main()
{
int T;
int n,m;
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&m);
ac.init();
for(int i=0;i<m;i++)
{
scanf("%s",s);
ac.insert(s,i);
}
for(int i=0;i<m;i++)
{
scanf("%d",&a[i]);
}
ac.build();
ac.solve(n);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: