首页 > 代码库 > POJ 3080 Blue Jeans KMP解法
POJ 3080 Blue Jeans KMP解法
使用KMP寻找最长的前缀的方法,比一般的暴力法有快了很多。
本题一般的暴力法需要的是O(m*n*n*n),其中m是有多少字符串,而n是字符串长度,而使用KMP就可以把时间效率提高到O(m*n*n),减少了一个n,提高了一个档次啦。
速度快很多。
准确来说应该是利用KMP寻找一个字符串A,在另一个字符串B任意位置出现的A的最长的前缀字符串。
理解好KMP的next table就好办了。每次查找到相等字符的时候,保存好最长的前缀。
注意本题的条件:选取最前的字典顺序输出。老害我错的条件。
#include <stdio.h> #include <string.h> #include <stdlib.h> const int MAX_N = 61; const int MAX_M = 11; const int ALP_LEN = 4; const int SIGNIFICANT = 3; char dict[MAX_M][MAX_N]; int kmpTable[MAX_N]; int n; inline int max(int a, int b) { return a > b ? a : b; } inline int min(int a, int b) { return a < b ? a : b; } int longestPrefix(char *chs, int len) { memset(kmpTable, 0, sizeof(int)*len); for (int i = 1, j = 0; i < len; i++) { if (chs[i] == chs[j]) kmpTable[i] = ++j; else if (j > 0) { j = kmpTable[j-1]; i--; } } int L = MAX_N - 1; for (int i = 1; i < n; i++) { int tmpAns = 0; for (int k = 0, j = 0; k < L && j < len; k++) { if (chs[j] == dict[i][k]) { ++j; tmpAns = max(tmpAns, j); } else if (j > 0) { j = kmpTable[j-1]; k--; } } len = min(len, tmpAns);//optimize } return len; } int main() { int T; scanf("%d", &T); while (T--) { scanf("%d", &n); getchar(); // get rid of '\n' for (int i = 0; i < n; i++) { gets(dict[i]); } int len = MAX_N - 1; int maxLen = 0; int pos = 0; char res[MAX_N] = {'\0'}; char subStr[MAX_N] = {'\0'}; for (int i = 0; i < len; i++)//search every start position { int tmpLen = longestPrefix(dict[0]+i, len-i); if (tmpLen >= maxLen) { if (tmpLen > maxLen) { maxLen = tmpLen; pos = i; } else//irritating alphabetic order { strncpy(res, dict[0]+pos, maxLen); strncpy(subStr, dict[0]+i, tmpLen); if (strcmp(res, subStr)) { maxLen = tmpLen; pos = i; } } } } if (maxLen < SIGNIFICANT) { puts("no significant commonalities"); } else { strncpy(res, dict[0]+pos, maxLen); printf("%s\n", res); } } return 0; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。