最短公共祖先
2016-07-12 16:52
148 查看
ACM模版
两个长字符串
参考题目链接:
HDU 1841 Find the Shortest Common Superstring题解
将KMP进行略微的改动,依然是查找匹配段,要求要么一个串包含另一个串,要么一个串的前缀等于另一个串的后缀。代码
/* * The shortest common superstring of 2 strings S1 and S2 is * a string S with|the minimum number of characters which * contains both S1 and S2 as a sequence of consecutive characters. */ const int N = 1000010; char a[2] ; int fail ; inline int max(int a, int b) { return (a > b) ? a : b; } int kmp(int &i, int &j, char* str, char* pat) { int k; memset(fail, -1, sizeof(fail)); for (i = 1; pat[i]; ++i) { for (k = fail[i - 1]; k >= 0 && pat[i] != pat[k + 1]; k = fail[k]); if (pat[k + 1] == pat[i]) { fail[i] = k + 1; } } i = j = 0; while (str[i] && pat[j]) { if (pat[j] == str[i]) { i++; j++; } else if (j == 0) { i++; // 第一个字符匹配失败,从str下一个字符开始 } else { j = fail[j - 1] + 1; } } if (pat[j]) { return -1; } else { return i - j; } } int main(int argc, const char * argv[]) { int T; scanf("%d", &T); while (T--) { int i, j, l1 = 0, l2 = 0; cin >> a[0] >> a[1]; int len1 = (int)strlen(a[0]), len2 = (int)strlen(a[1]), val; val = kmp(i, j, a[1], a[0]); // a[1]在前 if (val != -1) { l1 = len1; } else { // printf("i:%d, j:%d\n", i, j); if (i == len2 && j - 1 >= 0 && a[1][len2 - 1] == a[0][j - 1]) { l1 = j; } } val = kmp(i, j, a[0], a[1]); // a[0]在前 if (val != -1) { l2 = len2; } else { // printf("i:%d, j:%d\n", i, j); if (i == len1 && j - 1 >= 0 && a[0][len1 - 1] == a[1][j - 1]) { l2 = j; } } // printf("l1:%d,l2:%d\n",l1,l2); printf("%d\n", len1 + len2 - max(l1, l2)); } return 0; }
多个短字符串
首先用一个数组save[i][j]来保存第j个串加在第i个串之后,第i个串所增加的长度,比如alba bacau,把bacau加在alba后alba所增加的长度就为3.我们采用搜索的策略,以每一个串为第一个串进行搜索for(i = 1; i <= n; i++) {dfs(i)}// 以第i个串为第一个串进行搜索。 剪枝:主要是在搜索过程中,当前面一些串的长度比当前已经找到的min还大的话就剪去该枝。
相关文章推荐