HUNAN 11569 Just Another Knapsack Problem(AC自动机+dp)
http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11569&courseid=0
给出目标串,每个子串和对应的权值,然后要从子串中匹配出目标串并且权值最大.匹配的位置不能重复.
dp[i]为匹配到i这个位置时的最大价值,那么dp[i]=max(dp[i],dp[i-len[j]]+val[j]);
每次找到的匹配的子串在目标串的位置,然后动态转移。
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <vector> 5 #include <cstring> 6 #include <algorithm> 7 #include <string> 8 #include <set> 9 #include <functional> 10 #include <numeric> 11 #include <sstream> 12 #include <stack> 13 #include <map> 14 #include <queue> 15 16 #define CL(arr, val) memset(arr, val, sizeof(arr)) 17 18 #define ll long long 19 #define inf 0x7f7f7f7f 20 #define lc l,m,rt<<1 21 #define rc m + 1,r,rt<<1|1 22 #define pi acos(-1.0) 23 24 #define L(x) (x) << 1 25 #define R(x) (x) << 1 | 1 26 #define MID(l, r) (l + r) >> 1 27 #define Min(x, y) (x) < (y) ? (x) : (y) 28 #define Max(x, y) (x) < (y) ? (y) : (x) 29 #define E(x) (1 << (x)) 30 #define iabs(x) (x) < 0 ? -(x) : (x) 31 #define OUT(x) printf("%I64d\n", x) 32 #define lowbit(x) (x)&(-x) 33 #define Read() freopen("a.txt", "r", stdin) 34 #define Write() freopen("dout.txt", "w", stdout); 35 36 37 #define Nn 510007 38 #define Mc 26 39 40 using namespace std; 41 42 class Acautomaton 43 { 44 private: 45 46 int chd[Nn][Mc]; 47 int fail[Nn]; 48 int ID[Mc]; 49 int val[Nn]; 50 int Q[Nn]; 51 int sz; 52 int len[Nn]; 53 54 public: 55 int dp[101000]; 56 void Init() 57 { 58 fail[0] = 0; 59 for (int i = 0; i < Mc; ++i) 60 { 61 ID[i] = i; 62 } 63 } 64 void Reset() 65 { 66 CL(chd[0],0); 67 sz = 1; 68 } 69 int idx(char c) {return c-'a';} 70 void insert(char *s,int key) 71 { 72 int p = 0; 73 for (; *s; s++) 74 { 75 int k = ID[*s - 'a']; 76 if (!chd[p][k]) 77 { 78 CL(chd[sz],0); 79 val[sz] = 0; 80 len[sz]=0; 81 chd[p][k] = sz++; 82 } 83 len[chd[p][k]]=len[p]+1; 84 p = chd[p][k]; 85 } 86 val[p] =max(val[p], key); 87 } 88 void Build() 89 { 90 int *s = Q ,*e = Q,i; 91 for (i = 0; i < Mc; ++i) 92 { 93 if (chd[0][i]) 94 { 95 *e++ = chd[0][i]; 96 fail[chd[0][i]] = 0; 97 } 98 } 99 while (s != e) 100 { 101 int u = *s++; 102 for (i = 0; i < Mc; ++i) 103 { 104 int &v = chd[u][i]; 105 if (v) 106 { 107 *e++ = v; 108 fail[v] = chd[fail[u]][i]; 109 } 110 else v = chd[fail[u]][i]; 111 } 112 } 113 } 114 void find(char *T) { 115 int j=0; 116 for(int i=0,temp,c;T[i];i++) { 117 dp[i]=0; 118 c=idx(T[i]); 119 while(j&&!chd[j][c]) j=fail[j]; 120 j=chd[j][c]; 121 temp=j; 122 while(temp) { 123 if(val[temp]) { 124 //printf("%d\n",val[temp]); 125 if(i-len[temp]<0) //temp已经在目标串中出现,但是不能转移 126 dp[i]=max(dp[i],val[temp]); 127 else if(dp[i-len[temp]]) 128 dp[i]=max(dp[i],dp[i-len[temp]]+val[temp]); 129 printf("%d %d %d\n",i,dp[i],len[temp]); 130 } 131 temp=fail[temp]; 132 } 133 134 } 135 } 136 /* int solve(char *s) 137 { 138 int p = 0; 139 int k,ans = 0; 140 for (; *s; s++) 141 { 142 k = ID[*s - 'a']; 143 while (!chd[p][k] && p != 0) p = fail[p]; 144 145 p = chd[p][k]; 146 147 int rt = p; 148 while (rt != 0 && val[rt] != -1) 149 { 150 ans += val[rt]; 151 val[rt] = -1; 152 rt = fail[rt]; 153 } 154 } 155 return ans; 156 }*/ 157 }ac; 158 159 char s[100100],t[350]; 160 161 int main() 162 { 163 Read(); 164 int n,val,i; 165 while (~scanf("%s",s)) 166 { 167 ac.Reset(); ac.Init(); 168 scanf("%d",&n); 169 for (i = 0; i < n; ++i){ 170 scanf("%s %d",t,&val); 171 ac.insert(t,val); 172 } 173 ac.Build(); 174 ac.find(s); 175 //scanf("%s",tr); 176 printf("%d\n",ac.dp[strlen(s)-1]); 177 } 178 return 0; 179 }