您的位置:首页 > 其它

bzoj-2085 Hamsters

2015-08-31 16:50 351 查看
题意:

给出n个长度不大于100000的字符串;

现在要找出一个字符串包括m个这些字符串;

求这个字符串的最小长度;

数据保证字符串不互相包含;

n<=200,m<=1e9;

题解:

数据保证了字符串没有包含的情况。。

那么为了节约考虑,还是要让字符串叠在一起比较合算;

设f[i][j]表示i后面加个j字符串要再加多少字符;

这个怎么求呢?

Hash之后暴力;

RKhash可以O(1)拿出前缀后缀的Hash值,然后枚举长度就暴力出解了;

这里的复杂度看起来很大,但是PoPoQQQ大爷给了我们一些保障= =;

处理出这个之后,这实际上是一张图了;

要求的就是走m-1步的最短路;

然后就要上一个神奇的Floyd算法:倍增Floyd!

状态变成了三维f[l][i][j]表示i到j走1<<l步的方案数;

转移显然咯:f[l][i][j]=min(f[l-1][i][k]+f[l-1][k][j]);

这样的话,搞到m-1步的话就是将m-1按位分解的再处理了;

然后加上开头的字符串长度,取最小值;

注意字符串到自己本身是可以的,但是枚举长度时要从len-1开始;

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 220
#define M 110000
#define seed 131
using namespace std;
typedef long long ll;
char str
[M];
unsigned int hash
[M],pow[M];
ll f

,ans[2]

,len
;
ll cmp(int x,int y)
{
	for(ll i=x==y?len[x]-1:min(len[x],len[y]);i>=0;i--)
	{
		if(hash[x][len[x]]-hash[x][len[x]-i]*pow[i]==hash[y][i])
			return len[y]-i;
	}
}
int main()
{
	int n,m,i,j,k,l;
	ll x;
	scanf("%d%d",&n,&m);
	m--;
	pow[0]=1;
	for(i=1;i<M;i++)
		pow[i]=pow[i-1]*seed;
	for(i=1;i<=n;i++)
	{
		scanf("%s",str[i]+1);
		len[i]=strlen(str[i]+1);
		for(j=1;j<=len[i];j++)
		{
			hash[i][j]=hash[i][j-1]*seed+str[i][j];
		}
	}
	memset(f,0x3f,sizeof(f));
	for(i=1;i<=n;i++)
	{
		for(j=1;j<=n;j++)
		{
			f[0][i][j]=cmp(i,j);
		}
	}
	for(l=1;(1<<l)<=m;l++)
	{
		for(k=1;k<=n;k++)
		{
			for(i=1;i<=n;i++)
			{
				for(j=1;j<=n;j++)
				{
					f[l][i][j]=min(f[l][i][j],f[l-1][i][k]+f[l-1][k][j]);
				}
			}
		}
	}
	bool flag=0;
	for(l=0;(1<<l)<=m;l++)
	{
		if(1<<l&m)
		{
			if(!flag)
			{
				flag=1;
				memcpy(ans[0],f[l],sizeof(ans[0]));
				continue;
			}
			memset(ans[1],0x3f,sizeof(ans[1]));
			for(k=1;k<=n;k++)
			{
				for(i=1;i<=n;i++)
				{
					for(j=1;j<=n;j++)
					{
						ans[1][i][j]=min(ans[1][i][j],min(ans[0][k][j]+f[l][i][k],ans[0][i][k]+f[l][k][j]));
					}
				}
			}
			memcpy(ans[0],ans[1],sizeof(ans[0]));
		}
	}
	for(i=1,x=0x3f3f3f3f3f3f3f3fll;i<=n;i++)
	{
		for(j=1;j<=n;j++)
		{
			x=min(x,len[i]+ans[0][i][j]);
		}
	}
	printf("%lld\n",x);
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: