CF 346B. Lucky Common Subsequence(DP+KMP)
2013-09-25 10:06
246 查看
这题确实很棒。。又是无想法。。其实是AC自动机+DP的感觉,但是只有一个串,用kmp就行了。
dp[i][j][k],k代表前缀为virus[k]的状态,len表示其他所有状态串,处理出Ac[len][26]数组来,DP就可以了。状态转移那里一直没想清楚,wa了很多次,记录路径倒是不复杂,瞎搞搞就行。
dp[i][j][k],k代表前缀为virus[k]的状态,len表示其他所有状态串,处理出Ac[len][26]数组来,DP就可以了。状态转移那里一直没想清楚,wa了很多次,记录路径倒是不复杂,瞎搞搞就行。
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; char s1[103],s2[103],virus[103]; int dp[103][103][103]; int pre[103][103][103]; int pre1[103][103][103]; int Ac[111][31]; int next[103]; char ans[111]; void kmp() { int i,j,len,temp; len = strlen(virus); next[0] = -1; j = -1; for(i = 1; i < len; i ++) { while(j >= 0&&virus[j+1] != virus[i]) j = next[j]; if(virus[j+1] == virus[i]) j ++; next[i] = j; } for(i = 0; i < len; i ++) { for(j = 0; j < 26; j ++) { temp = i; while(temp >= 0&&virus[temp+1] != 'A'+j) temp = next[temp]; if(virus[temp+1] == 'A' + j) temp ++; if(temp == -1) Ac[i][j] = len; else Ac[i][j] = temp; } } for(i = 0; i < 26; i ++) { if(i + 'A' == virus[0]) Ac[len][i] = 0; else Ac[len][i] = len; } } int main() { int i,j,k,len1,len2,len,maxz,a,b,kk; scanf("%s%s%s",s1,s2,virus); len1 = strlen(s1); len2 = strlen(s2); len = strlen(virus); kmp(); for(i = 1; i <= len1; i ++) { for(j = 1; j <= len2; j ++) { for(k = 0; k <= len; k ++) { if(k == len-1) continue; if(dp[i][j][k] < dp[i-1][j][k]) { dp[i][j][k] = dp[i-1][j][k]; pre[i][j][k] = 2; pre1[i][j][k] = k; } if(dp[i][j][k] < dp[i][j-1][k]) { dp[i][j][k] = dp[i][j-1][k]; pre[i][j][k] = 3; pre1[i][j][k] = k; } if(s1[i-1] == s2[j-1]) { if(Ac[k][s1[i-1]-'A'] == len-1) continue; else if(dp[i][j][Ac[k][s1[i-1]-'A']] < dp[i-1][j-1][k] + 1) { dp[i][j][Ac[k][s1[i-1]-'A']] = dp[i-1][j-1][k] + 1; pre[i][j][Ac[k][s1[i-1]-'A']] = 1; pre1[i][j][Ac[k][s1[i-1]-'A']] = k; } } } } } maxz = 0; for(i = 1; i <= len1; i ++) { for(j = 1; j <= len2; j ++) { for(k = 0; k <= len; k ++) { if(maxz < dp[i][j][k]) { maxz = dp[i][j][k]; a = i; b = j; kk = k; } } } } if(maxz == 0) { printf("0\n"); return 0; } int num = 0; //printf("%d\n",maxz); while(a != 0&&b != 0) { if(pre[a][b][kk] == 1) { ans[num++] = s1[a-1]; kk = pre1[a][b][kk]; a --; b --; } else if(pre[a][b][kk] == 2) { kk = pre1[a][b][kk]; a --; } else if(pre[a][b][kk] == 3) { kk = pre1[a][b][kk]; b --; } else break; } for(i = num-1; i >= 0; i --) { printf("%c",ans[i]); } printf("\n"); return 0; }
相关文章推荐
- CF 432D(kmp)
- 【转】cf 825F - 19 String Compression 【kmp+dp】
- Bear and Blocks CF-574D(类似dp+思维)
- CF 119D String Transformation(KMP,哈希,枚举,各种优化)
- CF 299 div2 D. Tavas and Malekas(KMP)
- Hdu-5763 Another Meaning(DP+KMP)
- HDU 5763 Another Meaning (DP+KMP||后缀数组)
- Hduoj3336【dp+KMP】
- hdu5763 Another Meaning (DP+KMP)
- CF 460C Present 【DP+】主意
- cf 126B-Password(KMP)
- CF 149E Martian Strings(KMP)
- CF 372B Counting Rectangles is Fun [dp+数据维护]
- DP+KMP——Another Meaning ( HDU 5763 ) ( 2016 Multi-University Training Contest 4 1001 )
- CF 182D Common Divisors(KMP最短循环节,循环周期)
- CF825F:String Compression(dp & kmp)
- [KMP][字符串Hash] #93 div1 cf 126B Password
- codeforces 347 D Lucky Common Subsequence(dp+kmp)
- Educational Codeforces Round 21 G. Anthem of Berland(dp+kmp)
- [CF]291E. Tree-String Problem | dfs+kmp