您的位置:首页 > 其它

poj3080(简单题,串)

2015-06-02 17:48 281 查看
思路是二分长度(并没有太大的作用),然后kmp匹配,然后找出最大的串,如果有多个的话,要找出字典序最小的那个。

PS:这种找段落的,注意控制循环结束的条件。

#include "stdio.h"
#include "string.h"
#include "math.h"
#include <string>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <algorithm>
#include <iostream>
using namespace std;

#define MAXM 1
#define MAXN 1
#define max(a,b) a > b ? a : b
#define min(a,b) a < b ? a : b
#define Mem(a,b) memset(a,b,sizeof(a))
int Mod = 1000000007;
double pi = acos(-1.0);
double eps = 1e-6;

char s[15][65];
char mod[65];
int nnext[65];
char ans[65];
//char ss[65];

//得到next
void getNext(int len)
{
int j = -1, i = 0;
nnext[0] = -1;
for(i = 0; i < len; ){
if( j == -1 || mod[i] == mod[j] ){
i ++, j ++;
if( mod[i] == mod[j] )
nnext[i] = nnext[j];
else
nnext[i] = j;
}
else
j = nnext[j];
}
}

//kmp
bool isMatch(int x, int len)
{
int len1 = strlen(s[x]);
for(int i = 0, j = 0; i < len1;){
if( j == -1){
i ++, j ++;
continue;
}
if( s[x][i] == mod[j] ){
i ++, j ++;
if( j == len )
return true;
}
else
j = nnext[j];
}

return false;
}

int T, N;

bool isOk(int len){
bool flag = false;
int ll = strlen(s[0]);
//i <= ll - len
for(int i = 0; i <= ll - len; i ++){
int j, k;
for(j = 0, k = 0; j < len; j ++, k ++){
mod[k] = s[0][i+j];
}
mod[k] = 0;
getNext(k);

for(j = 1; j < N; j ++){
if( !isMatch(j,k) )
break;
}
if( j == N ){
if( strlen(ans) != len || strcmp(ans, mod) > 0){
strcpy(ans, mod);
flag = true;
}
}
}
return flag;
}

void solve()
{
for(int i = 0; i < N; i ++){
getchar();
scanf("%s",s[i]);
}

strcpy(ans, "");
int l = 2, r = strlen(s[0]);

//二分长度
while( l <= r ){
int mid = ( l + r + 1 ) >> 1;
if( isOk(mid) ){
l = mid + 1;
}
else
r = mid - 1;
}

if( strlen(ans) < 3 ){
printf("no significant commonalities\n");
}
else{
printf("%s\n",ans);
}
}

int main()
{
//	freopen("d:\\test.txt", "r", stdin);

while( cin>>T ){
while( T -- ){
cin>>N;
solve();
}
}

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