codeforces 154 A DP
蛮有意思的一个题
给你一个字符串,再给你k对字符
要求删掉一些字符使得字符串中不存在相邻的字符是这k对中的某一对
首先如果一个字符只出现在k对中的某一对中,那么可以贪心做
因为不会出现如下情况了 :
aaaabbbcccc
2
ab
ac
即不会出现删了之后前面的字符缩进来还会出现矛盾
但是当可以出现这种情况怎么办
DP就派上用场了
dp[i][j]表示前i个字符处理完了之后最后一个字符为(j+'a')的最小需要删掉的字符
那么到某个i位置的时候,首先不管它和前面留下来的最后一个字符有没有矛盾,都可以将它删除掉
如果没有矛盾,我们还可以将状态转移为以当前字符结尾
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstring> #include<algorithm> #include<string> #include<iostream> #include<cmath> #include<cstdlib> #include<vector> #include<set> #include<map> #include<queue> #include<stack> using namespace std; const int inf = ~0u>>2; int flag[27][27]; int dp[100010][27]; char s[100010]; int main() { int k; string op; while(scanf("%s",s+1)!=EOF) { cin>>k; memset(flag,0,sizeof(flag)); fill(dp[0],dp[100001],inf); while(k--) { cin>>op; flag[op[0]-'a'][op[1]-'a']=1; flag[op[1]-'a'][op[0]-'a']=1; } dp[0][26]=0; int len=strlen(s+1); for(int i=1;i<=len;i++) { for(int j=0;j<=26;j++) if(dp[i-1][j]!=inf) { int k=s[i]-'a'; dp[i][j]=min(dp[i][j],dp[i-1][j]+1);//将第i个字符删掉 if(!flag[j][k]) { dp[i][k]=min(dp[i][k],dp[i-1][j]);//没有矛盾,可以不删 } } } int ans=inf; for(int i=0;i<=26;i++) { if(dp[len][i]<ans) { ans=dp[len][i]; } } printf("%d\n",ans); } return 0; }