您的位置:首页 > 其它

2085: [Poi2010]Hamsters hash+倍增floyd

2016-03-07 13:51 239 查看
定义fk,i,j表示由第i个字符串开头第j个字符串结尾且一共有2k+1个子串的最短长度,然后倍增floyd转移一下。

#include<iostream>
#include<cstdio>
#include<cstring>
#define U unsigned long long
#define ll long long
#define N 205
#define L 100005
#define base 233
#define inf 1e18
using namespace std;
U T[L],hash
[L];
int len
;
ll f[32]

,A

,B

;
int n,m;
char s[L];
inline int read()
{
int a=0,f=1; char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
return a*f;
}
inline ll calc(int i,int j)
{
int MAXN;
if (i==j) MAXN=len[i]-1;
else MAXN=min(len[i],len[j]);
for (int k=MAXN;~k;k--)
if (hash[i][len[i]]-hash[i][len[i]-k]*T[k]==hash[j][k]) return len[j]-k;
}
int main()
{
n=read(); m=read()-1; T[0]=1;
for (int i=1;i<L;i++) T[i]=T[i-1]*base;
for (int i=1;i<=n;i++)
{
scanf("%s",s+1);
len[i]=strlen(s+1);
for (int j=1;j<=len[i];j++)
hash[i][j]=hash[i][j-1]*base+s[j];
}
memset(f,0x3f,sizeof(f));
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
f[0][i][j]=calc(i,j);
for (int p=1;(1<<p)<=m;p++)
for (int k=1;k<=n;k++)
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
f[p][i][j]=min(f[p][i][j],f[p-1][i][k]+f[p-1][k][j]);
int bit=0;
for (;(1<<bit)<=m;bit++)
if ((1<<bit)&m)
{
memcpy(A,f[bit],sizeof(A));
break;
}
for (bit++;(1<<bit)<=m;bit++)
if ((1<<bit)&m)
{
memset(B,0x3f,sizeof(B));
for (int k=1;k<=n;k++)
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
B[i][j]=min(B[i][j],min(A[i][k]+f[bit][k][j],f[bit][i][k]+A[k][j]));
memcpy(A,B,sizeof(A));
}
ll ans=inf;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
ans=min(ans,(ll)len[i]+A[i][j]);
cout << ans << endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: