蛋碎了,开始理解错题意的,以为跟上个题一样要替换。。。然后发现删除我不会啊,然后听宝哥讲了讲转移过程后,也不算难理解,主要是被前面的题给局限住思维了。
然后就是漫长的debug过程,手动构造数据,构造的我心碎了,最后看别人代码才发现错误,别人的代码实现方式和我明显不是一个风格的,我看的也很纠结啊。。。
在AC自动机构造关系的时候,开始只注意了-999的转移,然后慢慢debug后+上权值的转移,最后才发现999串的转移也要有,折腾了一天,终于过了。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <queue> 5 #include <algorithm> 6 #include <cstdlib> 7 using namespace std; 8 #define N 2000 9 #define INF 10000000 10 int t; 11 int trie[N][26]; 12 int o[N]; 13 int que[N]; 14 int flag[N]; 15 int fail[N]; 16 int wa[N]; 17 int dp1[N][256]; 18 int dp2[N][256]; 19 int goal1[N][256]; 20 int goal2[N][256]; 21 int num; 22 void CL() 23 { 24 num = 0; 25 memset(trie,-1,sizeof(trie)); 26 memset(o,0,sizeof(o)); 27 memset(flag,0,sizeof(flag)); 28 memset(wa,0,sizeof(flag)); 29 t = 1; 30 } 31 void insert(char *str,int x) 32 { 33 int i,root,len,sum; 34 root = 0; 35 len = strlen(str); 36 sum = 0; 37 for(i = 0; i < len; i ++) 38 { 39 if(trie[root][str[i]-'a'] == -1) 40 trie[root][str[i]-'a'] = t ++; 41 root = trie[root][str[i]-'a']; 42 } 43 if(x == 999) 44 { 45 flag[root] = 1<<num; 46 num ++; 47 } 48 else if(x == -999) 49 { 50 wa[root] = 1; 51 } 52 else 53 o[root] += x; 54 } 55 void build_ac() 56 { 57 int head,tail,front,i; 58 head = tail = 0; 59 for(i = 0; i < 26; i ++) 60 { 61 if(trie[0][i] != -1) 62 { 63 fail[trie[0][i]] = 0; 64 que[tail++] = trie[0][i]; 65 } 66 else 67 { 68 trie[0][i] = 0; 69 } 70 } 71 while(head != tail) 72 { 73 front = que[head++]; 74 flag[front] |= flag[fail[front]]; 75 wa[front] |= wa[fail[front]]; 76 o[front] += o[fail[front]]; 77 for(i = 0; i < 26; i ++) 78 { 79 if(trie[front][i] != -1) 80 { 81 que[tail++] = trie[front][i]; 82 fail[trie[front][i]] = trie[fail[front]][i]; 83 } 84 else 85 { 86 trie[front][i] = trie[fail[front]][i]; 87 } 88 } 89 } 90 } 91 int main() 92 { 93 int cas = 1,i,j,k,n,len,x,d; 94 char str[101]; 95 scanf("%d",&d); 96 while(d--) 97 { 98 scanf("%d",&n); 99 CL(); 100 for(i = 1; i <= n; i ++) 101 { 102 scanf("%s%d",str,&x); 103 insert(str,x); 104 } 105 build_ac(); 106 scanf("%s",str); 107 len = strlen(str); 108 for(i = 0; i <= t; i ++) 109 { 110 for(j = 0; j < (1<<num); j ++) 111 { 112 dp1[i][j] = INF; 113 dp2[i][j] = INF; 114 goal1[i][j] = -INF; 115 goal2[i][j] = -INF; 116 } 117 } 118 dp1[0][0] = 0; 119 goal1[0][0] = 0; 120 for(i = 0; i < len; i ++) 121 { 122 for(j = 0; j < t; j ++) 123 { 124 if(wa[j]) continue; 125 for(k = 0; k < (1<<num); k ++) 126 { 127 if(dp1[j][k] == INF) continue; 128 if(dp2[j][k] > dp1[j][k] + 1) 129 { 130 dp2[j][k] = dp1[j][k] + 1; 131 goal2[j][k] = goal1[j][k]; 132 } 133 else if(dp2[j][k] == dp1[j][k] + 1) 134 { 135 goal2[j][k] = max(goal2[j][k],goal1[j][k]); 136 } 137 int c = str[i] - 'a'; 138 if(wa[trie[j][c]]) continue; 139 int temp,val; 140 temp = k|flag[trie[j][c]]; 141 val = o[trie[j][c]]; 142 if(dp2[trie[j][c]][temp] > dp1[j][k]) 143 { 144 dp2[trie[j][c]][temp] = dp1[j][k]; 145 goal2[trie[j][c]][temp] = goal1[j][k] + val; 146 } 147 else if(dp2[trie[j][c]][temp] == dp1[j][k]) 148 { 149 goal2[trie[j][c]][temp] = max(goal2[trie[j][c]][temp],goal1[j][k] + val); 150 } 151 } 152 } 153 for(j = 0; j <= t; j ++) 154 { 155 for(k = 0; k < (1<<num); k ++) 156 { 157 dp1[j][k] = dp2[j][k]; 158 dp2[j][k] = INF; 159 goal1[j][k] = goal2[j][k]; 160 goal2[j][k] = -INF; 161 } 162 } 163 } 164 int ans1 = INF,ans2 = -INF; 165 for(i = 0; i < t; i ++) 166 { 167 if(ans1 > dp1[i][(1<<num)-1]) 168 { 169 ans1 = dp1[i][(1<<num)-1]; 170 ans2 = goal1[i][(1<<num)-1]; 171 } 172 else if(ans1 == dp1[i][(1<<num)-1]&&ans2 < goal1[i][(1<<num)-1]) 173 { 174 ans2 = goal1[i][(1<<num)-1]; 175 } 176 } 177 if(ans1 >= INF) 178 printf("Case %d: Banned ",cas++); 179 else 180 printf("Case %d: %d %d ",cas++,ans1,ans2); 181 } 182 return 0; 183 } 184 /* 185 9 186 3 187 abdc 2 188 bd 3 189 c 4 190 abdc 191 3 192 aba 999 193 a 6 194 ab 5 195 aba 196 3 197 3 198 ab -1 199 bc -2 200 d -3 201 abcd 202 */