看范围猜方程,应该是O(n)级别的
f[i]表示前i个合法的最小代价,转移需要枚举断点位置,O(n^2)
f[i]表示前i个合法留下的最大个数,同时更新距离最近的26个字母的位置,O(n)转移
f[i]=max{f[pos[j]+1} 0<=j<=25,j和a[i]可以同时出现
#include<iostream> #include<cstdio> using namespace std; const int MAXN=1000005; char a[MAXN],s[10]; bool fb[27][27]; int n,m; int f[MAXN],pos[32]; int main(){ scanf("%d%s",&n,a+1); for(int i=1;i<=n;i++) a[i]-='a'; scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%s",s);int x=s[0]-'a',y=s[1]-'a'; fb[x][y]=1;fb[y][x]=1; } for(int i=1;i<=n;i++){ f[i]=1; for(int j=0;j<26;j++){ if(!fb[a[i]][j]) f[i]=max(f[i],f[pos[j]]+1); } pos[a[i]]=i; } cout<<n-f[n]; return 0; }