您的位置:首页 > 产品设计 > UI/UE

POJ3080 Blue Jeans

2016-06-26 19:59 369 查看
一. 原题链接:http://poj.org/problem?id=3080

二. 题目大意:给出若干个字符串,让你在其中找出一个长度大于3的子串让其在所有字符串都出现过。

三. 思路:枚举所有子串,然后KMP匹配。枚举技巧:只枚举第一个字符串,因为要求的子串一定会出现在第一个字符串上(它会出现在每个字符串上),然后直接枚举所有后缀字符串,然后进入KMP里面,看最多能匹配多少个,KMP取的是跟其他所有串能匹配的最小长度的最长,首先保证当前模式串匹配到最长,然后匹配n-1个,在每个都保证最长的情况下,取最小。这样相当于枚举了所有的子串,然后在所有的子串中再取最长就行了。

四. 代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

const int MAX_N = 65,
INF = 0x3f3f3f3f;

int Next[MAX_N], num;
char pattern[MAX_N], text[11][65];

void getNext()
{
int i, k;
Next[0] = 0;
for(i = 1; pattern[i]; i++){
k = Next[i-1];
while(pattern[i] != pattern[k] && k>0)
k = Next[k-1];
if(pattern[i] == pattern[k])
Next[i] = k+1;
else
Next[i] = 0;
}
}

int KMP()
{
getNext();
int t, j, i, maxStr, minLen = INF;
for(t = 1; t < num; t++){
i = j = 0;
maxStr = -INF;
while(text[t][i] && pattern[j]){
while(text[t][i] != pattern[j] && j>0)
j = Next[j-1];
if(pattern[j] == text[t][i])
i++,j++;
else
i++;
maxStr = max(maxStr, j);
}
minLen = min(minLen, maxStr);
}
return minLen;
}

int main()
{
//freopen("in.txt", "r", stdin);
int T, i, res;
char resStr[MAX_N];

scanf("%d", &T);
while(T--){
res = -INF;
scanf("%d", &num);
for(i = 0; i < num; i++)
scanf("%s", text[i]);
for(i = 0; i <= 57; i++){
strcpy(pattern, text[0]+i);
int tmp = KMP();
char tmpStr[MAX_N];
strncpy(tmpStr, pattern, tmp);
tmpStr[tmp] = 0;
if(tmp > res){
res = tmp;
strcpy(resStr, tmpStr);
}
else if(tmp == res && strcmp(resStr, pattern) > 0){
strcpy(resStr, tmpStr);
}
}
if(res >= 3)
printf("%s\n", resStr);
else
printf("no significant commonalities\n");
}

return 0;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: