zoukankan      html  css  js  c++  java
  • HDU2296 Ring(AC自动机+DP)

    题目是给几个带有价值的单词。而一个字符串的价值是 各单词在它里面出现次数*单词价值 的和,问长度不超过n的最大价值的字符串是什么?

    依然是入门的AC自动机+DP题。。不一样的是这题要输出具体方案,加个字符数组记录每个状态最优情况的字符串即可。

    另外题目字典序是先考虑长度再考虑每一位单词;特别要注意,有一个非常坑的地方看了Disscus才知道——单词A包含单词B,那么只计算单词A不计算单词B。

    • dp[i][j]表示长度i(自动机上转移k步)后缀状态是自动机第j个结点的字符串的最大价值
    • dp[0][0]=0
    • 我为人人,dp[i][j]向26个字母转移到dp[i'][j']
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<queue>
     4 using namespace std;
     5 int tn,ch[1111][26],fail[1111],val[1111];
     6 void insert(char *s,int a){
     7     int x=0;
     8     for(int i=0; s[i]; ++i){
     9         int y=s[i]-'a';
    10         if(ch[x][y]==0) ch[x][y]=++tn;
    11         x=ch[x][y];
    12     }
    13     val[x]+=a;
    14 }
    15 void init(){
    16     memset(fail,0,sizeof(fail));
    17     queue<int> que;
    18     for(int i=0; i<26; ++i){
    19         if(ch[0][i]) que.push(ch[0][i]);
    20     }
    21     while(!que.empty()){
    22         int x=que.front(); que.pop();
    23         for(int i=0; i<26; ++i){
    24             if(ch[x][i]) que.push(ch[x][i]),fail[ch[x][i]]=ch[fail[x]][i];
    25             else ch[x][i]=ch[fail[x]][i];
    26             //val[ch[x][i]]+=val[ch[fail[x]][i]];
    27         }
    28     }
    29 }
    30 char str[111][11];
    31 int d[55][1111];
    32 char path[55][1111][55]; 
    33 int main(){
    34     int t,n,m,a;
    35     scanf("%d",&t);
    36     while(t--){
    37         tn=0;
    38         memset(ch,0,sizeof(ch));
    39         memset(val,0,sizeof(val));
    40         scanf("%d%d",&n,&m);
    41         for(int i=0; i<m; ++i) scanf("%s",str[i]);
    42         for(int i=0; i<m; ++i){
    43             scanf("%d",&a);
    44             insert(str[i],a);
    45         }
    46         init();
    47         memset(path,0,sizeof(path));
    48         memset(d,-1,sizeof(d));
    49         d[0][0]=0;
    50         for(int i=0; i<n; ++i){
    51             for(int j=0; j<=tn; ++j){
    52                 if(d[i][j]==-1) continue;
    53                 for(int k=0; k<26; ++k){
    54                     int &nd=d[i+1][ch[j][k]];
    55                     if(nd<d[i][j]+val[ch[j][k]]){
    56                         nd=d[i][j]+val[ch[j][k]];
    57                         strcpy(path[i+1][ch[j][k]],path[i][j]);
    58                         path[i+1][ch[j][k]][i]=k+'a';
    59                     }else if(nd==d[i][j]+val[ch[j][k]]){
    60                         char tmp[55]={0};
    61                         strcpy(tmp,path[i][j]);
    62                         tmp[i]=k+'a';
    63                         if(strcmp(tmp,path[i+1][ch[j][k]])<0) strcpy(path[i+1][ch[j][k]],tmp);
    64                     }
    65                 }
    66             }
    67         }
    68         int resi=0,resj=0;
    69         for(int i=1; i<=n; ++i){
    70             for(int j=0; j<=tn; ++j){
    71                 if(d[resi][resj]<d[i][j]) resi=i,resj=j;
    72                 else if(d[resi][resj]==d[i][j] && resi==i && strcmp(path[resi][resj],path[i][j])>0) resi=i,resj=j;    
    73             }
    74         }
    75         puts(path[resi][resj]);
    76     }
    77     return 0;
    78 }
  • 相关阅读:
    C#中 @ 的用法
    ASP.NET页面间传值
    ASP.NET中常用的文件上传下载方法
    把图片转换为字符
    把图片转换为字符
    JavaScript 时间延迟
    Using WSDLs in UCM 11g like you did in 10g
    The Definitive Guide to Stellent Content Server Development
    解决RedHat AS5 RPM安装包依赖问题
    在64位Windows 7上安装Oracle UCM 10gR3
  • 原文地址:https://www.cnblogs.com/WABoss/p/5172335.html
Copyright © 2011-2022 走看看