给出一个字符串,然后给出K个约束 ,每个约束包含两个字母,表示这两个字母不能在字符串中相邻存在,现在我们需要删除一些字符,使得字符串是合法的。
输出最少删除的字符个数。
思路:
希望删除的最少,反过去想就是希望留下来的最多,那么我们设定Dp【i】表示到位子i,能够留下来的字符串最长长度,那么对应我们能够写出状态转移方程:
Dp【i】=max(Dp【i】,Dp【j】+1),这里需要保证a【j】和a【i】不冲突。
显然直接这样去暴力Dp会超时,我们知道,输入只包含字符,所以我们不如设定temp【i】,表示以字符i结尾的Dp最大值。
那么我们就有:
Dp【i】=max(Dp【i】,temp【j】+1),这里同样需要保证字符j和字符a【i】不冲突才行。
那么:Ans=n-max(Dp【i】)
Ac代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
char a[150000];
int bid[300][300];
int dp[150000];
int temp[300];
int main()
{
while(~scanf("%s",a+1))
{
int n=strlen(a+1);
memset(dp,0,sizeof(dp));
memset(temp,0,sizeof(temp));
memset(bid,0,sizeof(bid));
int k;scanf("%d",&k);
while(k--)
{
char b[45];
scanf("%s",b);
bid[b[0]][b[1]]=1;
bid[b[1]][b[0]]=1;
}
int output=0;
for(int i=1;i<=n;i++)
{
if(i==1)
{
dp[i]=1;
temp[a[i]]=1;
}
else
{
for(int j='a';j<='z';j++)
{
if(bid[a[i]][j]==0)
{
dp[i]=max(dp[i],temp[j]+1);
}
}
temp[a[i]]=max(temp[a[i]],dp[i]);
}
output=max(output,dp[i]);
}
printf("%d\n",n-output);
}
}