Blue Jeans poj3080

   字典树!奋斗我的做法是将前n-1个串分成若干子串(长度大于2),然后存入字典树,再将第n串也分成若干子串,进行匹配。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
	int count;//记录子串的数目
	int cur;//记录当前子串来自哪一原串(防止同一原串的相同子串重复记录)
	node *next[26];
}memory[1000000],*root;

struct word
{
	char s[65];
	bool operator<(const word &t)const
	{
		return strcmp(s,t.s)<0;
	}
}ans[60];//最长公共子串可能有多种,所以要多记录下来,然后按字典序排序

int ptr,n;
char str[65];


node *build_node()
{
	node *p=&memory[ptr++];
	for(int i=0;i<26;i++)
		p->next[i]=NULL;
	p->cur=-1;
	p->count=0;
	return p;
}

bool insert_tree(int s,int e,int id)
{
	int index;
	node *p=root;
	for(int i=s;i<=e;i++)
	{
		index=str[i]-65;
		if(p->next[index]==NULL)
			p->next[index]=build_node();
		p=p->next[index];
	}
	if(id!=p->cur)//该子串在当前串中没重复出现
	{
		p->cur=id;
		p->count++;
		if(p->count==n)
			return true;
	}
	return false;
}

int main()
{
	int cnt,t;
	bool ok;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		ptr=0;
		root=build_node();
		for(int i=0;i<n-1;i++)//先将前n-1个串分别分成若干子串,然后存在字典树中
		{
			scanf("%s",str);
			for(int j=0;j<60;j++)
				for(int k=j+2;k<60;k++)
					insert_tree(j,k,i);
		}
		ok=false;
		scanf("%s",str);
		cnt=0;
		for(int len=60;len>2;len--)
		{
			if(ok)
				break;
			for(int i=0;i+len-1<60;i++)
				if(insert_tree(i,i+len-1,n-1))
				{
					ok=true;
					int j;
					for(j=i;j<=i+len-1;j++)
						ans[cnt].s[j-i]=str[j];
					ans[cnt].s[j-i]='\0';
				}
		}
		if(!ok)
		{
			printf("no significant commonalities\n");
			continue;
		}
		sort(ans,ans+cnt);
		printf("%s\n",ans[0].s);
	}
	return 0;
}


 

你可能感兴趣的:(Blue Jeans poj3080)