题解 S

传送门

KMP自动机,需要预处理优化跳next的过程

  • 特别注意CCF的arbiter算空间的时候是按MB而不是MiB算的,256MB折合下来只有244MiB多点
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 8010
#define ll long long
//#define int long long

int n, m;
char s[N], t[N];

namespace force{
	int ans=INF, nxt[N], top;
	char sta[N];
	bool check() {
		for (int i=1,j=0; i<=top; ++i) {
			while (j && (j==m||sta[i]!=t[j+1])) j=nxt[j];
			if (sta[i]==t[j+1]) ++j;
			if (j==m) return 1;
		}
		// cout<<"top: "<<top<<endl;
		// cout<<"sta: "; for (int i=1; i<=top; ++i) cout<<sta[i]; cout<<endl;
		return 0;
	}
	void solve() {
		nxt[1]=0;
		for (int i=2,j=0; i<=m; ++i) {
			while (j && t[j+1]!=t[i]) j=nxt[j];
			if (t[j+1]==t[i]) ++j;
			nxt[i]=j;
		}
		int lim=1<<n;
		for (int s0=0,s2,cnt; s0<lim; ++s0) {
			s2=s0; cnt=0; top=0;
			if (s0) do {s2&=s2-1; ++cnt;} while (s2);
			if (n-cnt>=ans) continue;
			for (int i=0; i<n; ++i) if (s0&(1<<i)) sta[++top]=s[i+1];
			if (!check()) ans=min(ans, n-cnt);
		}
		printf("%d\n", ans);
		exit(0);
	}
}

namespace task1{
	short nxt[N], dp[8010][8010], st[8010][26], ans=16380;
	const short one=1;
	inline short min(short a, short b) {return a>b?b:a;}
	void solve() {
		memset(dp, 0x3f, sizeof(dp));
		// cout<<dp[1][1]<<endl;
		// cout<<double(sizeof(nxt)+sizeof(dp)+sizeof(st)+sizeof(s)*2+sizeof(force::nxt)+sizeof(force::sta))/1024/1024<<endl;
		nxt[1]=0;
		for (int i=2,j=0; i<=m; ++i) {
			while (j && t[j+1]!=t[i]) j=nxt[j];
			if (t[j+1]==t[i]) ++j;
			nxt[i]=j;
		}
		for (int i=0; i<m; ++i) {
			for (int j=0,p; j<26; ++j) {
				p=i;
				while (p && j!=t[p+1]-'a') p=st[nxt[p]][j];
				// if (t[p+1]-'a'==j) ++p;
				st[i][j]=p;
			}
		}
		dp[1][0]=0;
		for (int i=1; i<=n; ++i) {
			for (int j=0,j2; j<m; ++j) {
				if (s[i]==t[j+1]) {
					if (j+1<m) dp[i+1][j+1]=min(dp[i+1][j+1], dp[i][j]);
					dp[i+1][j]=min(dp[i+1][j], dp[i][j]+one);
				}
				else {
					dp[i+1][j]=min(dp[i+1][j], dp[i][j]+one);
					j2=st[j][s[i]-'a'];
					if (t[j2+1]==s[i]) ++j2;
					dp[i+1][j2]=min(dp[i+1][j2], dp[i][j]);
				}
			}
		}
		// for (int i=1; i<=n+1; ++i) for (int j=0; j<m; ++j) printf("dp[%d][%d]=%d\n", i, j, dp[i][j]);
		for (int i=0; i<m; ++i) ans=min(ans, dp[n+1][i]);
		printf("%d\n", ans);
		exit(0);
	}
}

signed main()
{
	freopen("s.in", "r", stdin);
	freopen("s.out", "w", stdout);

	// cout<<double(sizeof(tem))/1024/1024<<endl;
	scanf("%s%s", s+1, t+1);
	n=strlen(s+1); m=strlen(t+1);
	// force::solve();
	task1::solve();

	return 0;
}
posted @ 2021-10-18 09:23  Administrator-09  阅读(0)  评论(0编辑  收藏  举报