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); } }
相关文章推荐
- 几种有趣的不常见排序
- HTML5培训第15节课堂笔记(HTML5+maps,geolocation)
- sql server学习
- UVA 10652 - Board Wrapping(二维凸包)
- PHP接口入门分析实例
- 寻找水王
- SQL FORMAT() 函数实例
- android中ListView控件&&onItemClick事件中获取listView传递的数据
- 查看文本[Linux]
- 深度学习学习笔记
- 《栈 队列》——栈与队列(Java)
- ubuntu14.04 下的hello sky 例子
- hdu 5248(二分+贪心)
- winform 分页控件
- json字符串与json对象的相互转换
- CSS颜色属性,边框属性
- 同志们千万细心
- 回文字符串
- 如何去掉按钮的立体效果
- Activity的生命周期详述