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 }
  • 相关阅读:
    jdk1.8 操作List<Map> 多个map 具有相同的key 进行分组合并重组数据
    js获取字符中连续的值
    Java线程ABA问题
    Oracle递归查询语句
    Oracle学习笔记表连接(十六)
    Docker For Mac没有docker0网桥
    awk 和 sed (Stream Editor)
    WARNING: firstResult/maxResults specified with collection fetch; applying in memory!
    iptables编写规则
    InnoDB Next-Key Lock
  • 原文地址:https://www.cnblogs.com/WABoss/p/5172335.html
Copyright © 2011-2022 走看看