Kmp+状压dp求助
查看原帖
Kmp+状压dp求助
802655
ZhuYF1029楼主2024/3/4 20:56

思路没错吧?

将包含的字符串融合,再状压dp

死亡回放

Code

#include <bits/stdc++.h>
#define int long long
#define inf 4557430888798830399
#define pii pair<int,int>
#define fi first 
#define se  second
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
const int maxn=20,maxl=2e5+10;
using namespace std;
int n,pre[maxl];
void getpre(string& s){
	pre[0]=0;
	int j=0;
	for(int i=1;i<s.size();i++){
		while(j>0 && s[i]!=s[j]) j=pre[j-1];
		if(s[i]==s[j]) j++;
		pre[i]=j;
	}
}
bool find(string& s,string& t){
	for(int i=0,j=0;i<s.size();i++){
		while(j>0 && s[i]!=t[j]) j=pre[j-1];
		if(s[i]==t[j]) j++;
		if(j==t.size()) return true;
	}
	return false;
}
int query(string& s,string& t){
	int i,j;
	for(i=0,j=0;i<s.size();i++){
		while(j>0 && s[i]!=t[j]) j=pre[j-1];
		if(s[i]==t[j]) j++;
	}
	return t.size()-j;
}
string s[maxn];
int f[maxn],dp[1<<maxn][maxn],ans=inf;
vector<pii> g[maxn]; 
void update(int& x,int y){
	x=min(x,y);
}
signed main(){
	cin >> n;
	for(int i=0;i<n;i++){
		cin >> s[i];
	}
	for(int i=0;i<n;i++){
		getpre(s[i]);
		for(int j=0;j<n;j++){
			if(find(s[i],s[j])){
				f[i]|=1<<j;
			}
		}
		for(int j=0;j<n;j++){
			g[i].pb(mp(j,query(s[i],s[j])));
		}
	}
	memset(dp,0x3f,sizeof(dp));
	for(int i=0;i<n;i++){
		update(dp[f[i]][i],(int)s[i].size());
	}
	for(int mask=0;mask<1<<n;mask++){
		for(int i=0;i<n;i++){
			if(dp[mask][i]==inf) continue;
			for(int j=0;j<g[i].size();j++){
				update(dp[mask|f[g[i][j].fi]][g[i][j].fi],dp[mask][i]+g[i][j].se);
			}
		}
	}
	for(int i=0;i<n;i++){
		ans=min(ans,dp[(1<<n)-1][i]);
	}
	cout << ans << endl;
	return 0;
}
2024/3/4 20:56
加载中...