P3502 [POI 2010] CHO-Hamsters 题解

题目链接:P3502 [POI 2010] CHO-Hamsters

注意到任意两个串都不会存在包含的关系,所以每增加一次出现次数距离一定增加并且只和上一个名字是什么有关,使用 $ (\min, +) $ 矩阵快速幂加速即可。对于求从名字 $ x $ 到名字 $ y $ 要增加的字符个数,直接哈希暴力求即可,这部分的时间复杂度是 $ \sum_i \sum_j min(|S_i|,|S_j|) \le \sum_i \sum_j |S_j| = nL $,总时间复杂度为 $ O(nL+n^3logm) $。

代码:

#include<bits/stdc++.h>
#define time(null) chrono::steady_clock::now().time_since_epoch().count()
#define int long long
#define uint unsigned long long
#define debug() cout<<"come here\n"
#define INF 0x3f3f3f3f3f3f3f3f
#define pii pair<int,int>
#define pb push_back
#define Code return
#define by 0
#define MCYYDS ;
using namespace std;
int qpow(int a,int b,int p=INF){int ret=1;while(b){if(b&1)ret=(ret*a)%p;a=(a*a)%p;b>>=1;}return ret;}
inline int read(){int ret=0,f=1;char ch=getchar();while(ch<'0'||ch>'9')f=(ch=='-'?-1:f),ch=getchar();while(ch>='0'&&ch<='9')ret=(ret<<3)+(ret<<1)+(ch^48),ch=getchar();return ret*f;}
inline void write(int x){if(x<0){putchar('-');write(-x);return ;}if(x>9)write(x/10);putchar((char)(x%10+48));}
inline void writech(int x,char ch){write(x);putchar(ch);}
struct matrix{
	int n,a[205][205];
	void init(int _n)
	{
		n=_n;
		for(int i=0;i<=n;i++)
		{
			for(int j=0;j<=n;j++)
			{
				a[i][j]=INF*(!(i==j));
			}
		}
	}
};
matrix mul(matrix &a,matrix &b)
{
	matrix c;
	c.n=a.n;
	for(int i=0;i<=c.n;i++)
	{
		for(int j=0;j<=c.n;j++)
		{
			c.a[i][j]=INF;
		}
	}
	for(int i=0;i<=c.n;i++)
	{
		for(int k=0;k<=c.n;k++)
		{
			for(int j=0;j<=c.n;j++)
			{
				c.a[i][j]=min(c.a[i][j],a.a[i][k]+b.a[k][j]);
			}
		}
	}
	return c;
}
string s[205];
vector<uint> hsh[205];
uint pw[100005];
uint gethsh(int id,int l,int r)
{
	if(!l)return hsh[id][r];
	return hsh[id][r]-hsh[id][l-1]*pw[r-l+1];
}
int getdis(int x,int y,int i)
{
	for(int len=min((int)s[x].size(),(int)s[y].size()-i);len>=1;len--)
	{
		if(gethsh(x,s[x].size()-len,s[x].size()-1)==gethsh(y,0,len-1))return s[y].size()-len;
	}
	return s[y].size();
}
signed main()
{
//	ios::sync_with_stdio(0);
//	cin.tie(0);
//	cout.tie(0);
	pw[0]=1;
	for(int i=1;i<=100000;i++)
	{
		pw[i]=pw[i-1]*131;
	}
	int n=read(),m=read();
	for(int i=1;i<=n;i++)
	{
		cin>>s[i];
		hsh[i].resize(s[i].size());
		hsh[i][0]=s[i][0];
		for(int j=1;j<s[i].size();j++)
		{
			hsh[i][j]=hsh[i][j-1]*131+s[i][j];
		}
	}
	matrix a,ret;
	a.init(n);
	ret.init(n);
	for(int i=0;i<=n;i++)
	{
		for(int j=0;j<=n;j++)
		{
			if(j==0)a.a[i][j]=INF;
			else if(i==0)a.a[i][j]=s[j].size();
			else if(i==j)a.a[i][j]=getdis(i,j,1);
			else a.a[i][j]=getdis(i,j,0);
		}
	}
	while(m)
	{
		if(m&1)ret=mul(ret,a);
		a=mul(a,a);
		m>>=1;
	}
	int ans=INF;
	for(int i=1;i<=n;i++)
	{
		ans=min(ans,ret.a[0][i]);
	}
	writech(ans,'\n');
	Code by MCYYDS
}

posted @ 2026-09-28 14:16  MCYYDS  阅读(4)  评论(0)    收藏  举报