朴素的DP + 递归打印路径,然后TLE了,不AC的代码不想往硬盘放,暂时在这留存一下,以后有机会再看【会有机会么】。。。
title见:猛点我
TLE版:
#include <iostream> #include <cmath> #include <algorithm> #include <string> #include <cstring> #include <cstdio> using namespace std; const int INF = 1100; int pre[INF], now[INF]; int path[INF][INF]; char ch_aryA[INF], ch_aryB[INF]; void dp_lcs(int lenA, int lenB) { int len = max(lenA, lenB); for(int i = 0; i <= len; ++ i) { pre[i] = now[i] = 0; for(int j = 0; j <= lenB; ++ j) path[i][j] = 0; } for(int i = 0; i < lenA; ++ i) { for(int j = 0; j < lenB; ++ j) { if(ch_aryA[i] == ch_aryB[j]) { now[j] = now[j - 1] + 1; path[i][j] = 1; } else if(now[j - 1] > pre[j])//当前层的j - 1和上一层的j { now[j] = now[j - 1]; path[i][j] = 2; } else if(now[j - 1] <= pre[j]) { now[j] = pre[j]; path[i][j] = 3; } } for(int j = 0; j <= len; ++ j) pre[j] = now[j]; //memmove(pre, now, sizeof(pre));//safer than memcpy }//最终内层循环的长度值是最后结果,即:now[lenB - 1] } void print_path(int i, int j, char str[]) { if(i < 0 || j < 0) return; if(1 == path[i][j]) { print_path(i - 1, j - 1, str); printf("%c %d %d/n", str[i], i + 1, j + 1); } else if(2 == path[i][j]) print_path(i, j - 1, str);//回溯到上个转移过来的状态 else if(3 == path[i][j]) print_path(i - 1, j, str); } int main() { int T; scanf("%d", &T); int lenA, lenB; for(int i = 1; i <= T; ++ i) { scanf("%d %s", &lenA, ch_aryA); scanf("%d %s", &lenB, ch_aryB); printf("case %d ", i); dp_lcs(lenA, lenB); if(now[lenB - 1] <= 1) { puts("N"); continue; } else printf("Y/n%d/n", now[lenB - 1]); print_path(lenA - 1, lenB - 1, ch_aryA); } return 0; }
测试数据:
Input:35 ddacc3 cac7 cbbccbc4 aaca4 cbeb5 fdcebOutput:case 1 Y2a 3 2c 4 3case 2 Ncase 3 Y3c 1 3e 3 4b 4 5 窃以为这个应该SPJ吧,第一个case输出两个CC不也对么
