AT_abc343_g [ABC343G] Compress Strings 题解

唐题。

考虑瞎状压,fi,Sf_{i,S} 表示末尾的字符串是 sis_i,目前 SS 这个二进制状态为 11 的位置已经是子串了。转移直接枚举上一个位置哈希。注意要把本身就在另一个字符串的子串中的删掉并去重。

#include <bits/stdc++.h>
using namespace std;
//#define int long long

using ll = long long;

const int N = 22, MOD = 1e9 + 9, HSMOD = 1610612741, HSMOD2 = 998244353; // Remember to change

int n, m, q, t, a[N];
mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());

long long qpow(long long a, long long b)
{
	long long res = 1ll, base = a;
	while (b)
	{
		if (b & 1ll) res = res * base % MOD;
		base = base * base % MOD;
		b >>= 1ll;
	}
	return res;
}

bool isprime(int x)
{
	if (x == 1) return 0;
	for (int i = 2; 1ll * i * i <= x; i++) if (x % i == 0) return 0;
	return 1;
}

namespace FastIo
{
	#define QUICKCIN ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
	int read()
	{
		char ch = getchar();
		int x = 0, f = 1;
		while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
		while (ch == '-')
		{
			f = -f;
			ch = getchar();
		}
		while (ch >= '0' && ch <= '9')
		{
			x = (x << 1) + (x << 3) + (ch ^ 48);
			ch = getchar();
		}
		return x * f;
	}
	template<class T>
	void write(T x)
	{
		if (x < 0)
		{
			putchar('-');
			x = -x;
		}
		if (x > 9) write(x / 10);
		putchar(x % 10 + '0');
	}
	template<class T>
	void writeln(T x)
	{
		write(x);
		putchar('\n');
	}
}

template<typename T>
class Bit
{
public:
	T lowbit(T x)
	{
		return x & -x;
	}
	T tr[N];
	void add(T x, T y)
	{
		while (x < N)
		{
			tr[x] += y;
			x += lowbit(x);
		}
	}
	T query(T x)
	{
		T sum = 0;
		while (x)
		{
			sum += tr[x];
			x -= lowbit(x);
		}
		return sum;
	}
};

int f[N][1<<21];
string s[N];

struct Two_Hash
{
	long long hs1,hs2;
	Two_Hash()=default;
	Two_Hash(long long h1,long long h2):hs1(h1),hs2(h2){}
	Two_Hash operator+(const Two_Hash x)
	{
		return Two_Hash((hs1+x.hs1)%MOD,(hs2+x.hs2)%HSMOD);
	}
	Two_Hash operator-(const Two_Hash x)
	{
		return Two_Hash((hs1-x.hs1+MOD)%MOD,(hs2-x.hs2+HSMOD)%HSMOD);
	}
	Two_Hash operator-(const long long x)
	{
		return Two_Hash((hs1-x+MOD)%MOD,(hs2-x+HSMOD)%HSMOD);
	}
	Two_Hash operator+(long long x)
	{
		return Two_Hash((hs1+x)%MOD,(hs2+x)%HSMOD);
	}
	Two_Hash operator*(const Two_Hash x)
	{
		return Two_Hash((hs1*x.hs1)%MOD,(hs2*x.hs2)%HSMOD);
	}
	Two_Hash operator*(const long long x)
	{
		return Two_Hash((hs1*x)%MOD,(hs2*x)%HSMOD);
	}
	bool operator==(const Two_Hash x)
	{
		return (hs1==x.hs1&&hs2==x.hs2);
	}
}; 

const int M=5e5+5;

Two_Hash powe[M];

vector<Two_Hash> v1[N],v2[N];
int ans[N][N];

int getres(int x,int y)
{
	int cnt=0;
	for(int i=0;i<min(s[x].size(),s[y].size());i++)
	{
		if(v1[y][i]==v2[x][i]) cnt=i+1;
	}
	for(int i=0;i+s[y].size()-1<s[x].size();i++)
	{
		Two_Hash rr=v1[x][i+s[y].size()-1]-(i?v1[x][i-1]:Two_Hash(0,0))*powe[s[y].size()];
		//cout<<"!!!!!: " <<rr.hs1<<" "<<rr.hs2<<"\n";
		if(rr==v1[y][s[y].size()-1])
		{
			cnt=s[y].size();
		} 
	}
	return cnt;
}

vector<string> vecs;

int main()
{
	ios::sync_with_stdio(0), cin.tie(nullptr), cout.tie(nullptr);
	memset(f,0x3f,sizeof f);
	cin>>n;
	f[0][0]=0;
	powe[0]=Two_Hash(1,1);
	for(int i=1;i<M;i++) powe[i]=powe[i-1]*26;
	set<string> ss;
	for(int i=1;i<=n;i++)
	{
		cin>>s[i];
		ss.insert(s[i]);
	}
	sort(s+1,s+n+1);
	n=unique(s+1,s+n+1)-s;
	if(ss.size()==1)
	{
		cout<<s[1].size()<<"\n";
		return 0;
	}
	for(int i=1;i<=n;i++)
	{
		v1[i].clear(),v2[i].clear();
		auto g=Two_Hash(0,0);
		for(auto&j:s[i])
		{
			g=g*26+(j-'a'+1);
			v1[i].emplace_back(g);
		}
		reverse(s[i].begin(),s[i].end());
		g=Two_Hash(0,0);
		Two_Hash nw=Two_Hash(1ll,1ll);
		for(auto&j:s[i])
		{
			g=Two_Hash(j-'a'+1,j-'a'+1)*nw+g;
			nw=nw*26;
			v2[i].emplace_back(g);
		}
		reverse(s[i].begin(),s[i].end());
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++) ans[i][j]=getres(i,j);
	}
	for(int i=1;i<=n;i++)
	{
		bool f=1;
		for(int j=1;j<=n;j++) 
		{
			if(ans[j][i]==s[i].size()&&i!=j)
			{
				f=0;
			} 
		}
		if(f) vecs.emplace_back(s[i]);
	}
	n=vecs.size();
	for(int i=1;i<=n;i++) 
	{
		v1[i].clear(),v2[i].clear();
		s[i]=vecs[i-1];
		auto g=Two_Hash(0,0);
		for(auto&j:s[i])
		{
			g=g*26+(j-'a'+1);
			v1[i].emplace_back(g);
		}
		reverse(s[i].begin(),s[i].end());
		g=Two_Hash(0,0);
		Two_Hash nw=Two_Hash(1ll,1ll);
		for(auto&j:s[i])
		{
			g=Two_Hash(j-'a'+1,j-'a'+1)*nw+g;
			nw=nw*26;
			v2[i].emplace_back(g);
		}
		reverse(s[i].begin(),s[i].end());
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++) ans[i][j]=getres(i,j);
	}
	for(int j=1;j<(1<<n);j++)
	{
		for(int i=1;i<=n;i++)
		{
			if(!((j>>(i-1))&1)) continue;
			if(__builtin_popcount(j)==1)
			{
				f[i][j]=s[i].size();
			}
			else
			{
				for(int k=1;k<=n;k++)
				{
					if(k==i||((!((j>>(k-1))&1)))) continue;
					f[i][j]=min(f[i][j],f[k][j-(1<<(i-1))]+(int)s[i].size()-ans[k][i]);
				}
			}
			//cout<<"???????: "<<f[2][1]<<"\n";
		}
	}
	int ans=(int)1e9;
	for(int i=1;i<=n;i++) ans=min(ans,f[i][(1<<n)-1]);
	cout<<ans<<"\n";
	return 0;
}
posted @ 2024-03-05 18:15  HappyBobb  阅读(0)  评论(0编辑  收藏  举报  来源