/*
状态表示
{
1.集合:dp[i]表示前i个字符最多保留多少个
2.属性:max
}
状态计算
{
1.不保留这个字符:那么这个就是与上个状态一样:dp[i]=dp[i-1]
2.保留这个字符:那么就要把中间的都删掉,即是把这个字符与前面出现过这个字符之间的字符全都删掉,再加上这两个字符:
dp[i]=dp[pre[s[i]-'a']-1]+2(前提是要前面出现过)
}
状态转移方程:dp[i]=max(dp[i-1],dp[pre[s[i]-'a']-1]+2);
*/
#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
int main()
{
int t; cin>>t;
while(t--)
{
string s; cin>>s;
int n=s.size();
vector<int> dp(n+1,0),pre(30,0);
s=" "+s;//因为下面循环是从一开始的所以需要把字符串往后移一位
for(int i=1;i<=n;i++)
{
dp[i]=dp[i-1];
if(pre[s[i]-'a']) dp[i]=max(dp[i],dp[pre[s[i]-'a']-1]+2);
pre[s[i]-'a']=i;//初始化某个字符出现过的位置
}
cout<<n-dp[n]<<endl;//用总数减去保留的字符就是需要删去的字符
}
return 0;
}
DP(遇到的题目可以dp的)
最新推荐文章于 2025-05-24 09:26:43 发布