Code[VS] 3301 Square words

来源:互联网 发布:90年代网络歌曲 编辑:程序博客网 时间:2024/05/17 22:07

【题意】

定义square words为:

1.长度为偶数;

2.前一半等于后一半;

比如abcabc和aaaa都是square words,但是abcabcab和aaaaa都不是。

现在有一个长度为n的字符串,求至少要删掉多少个字符,使得剩下的字符串是square words。

(n ≤ 500)

【构思】

数据范围不大,n^3即可;

前一半=后一半,说明有两部分相同,从某个点断开有子序列相同;

枚举断点,然后变成两个字符串p,q,字符串从前往后匹配,满足无后效性;

设f[i][j]表示把p匹配到第i位,q匹配到第j位的最长子序列的长度;

则f[i][j]=max(f[i-1][j-1]+(p[i]==p[j]),f[i-1][j],f[i][j-1]),

然后结果就取字符串长度-最大的子序列长度。

时间复杂度:O(N^3)

空间复杂度:O(N^2)

【实现】

#include <cstdio>

#include <cstring>

#include <cstdlib>


using namespace std;


const int N=510;


int ls,res,f[N][N];

char s[N],p[N],q[N];


int max(int i,int j)

{

return i>j?i:j;

}


int get(int lp,int lq)

{

memset(p,0,sizeof p);

memset(q,0,sizeof q);

memset(f,0,sizeof f);

for (int i=1;i<=lp;i++) p[i]=s[i-1];

for (int i=1;i<=lq;i++) q[i]=s[i+lp-1];

for (int i=1;i<=lp;i++)

for (int j=1;j<=lq;j++) f[i][j]=max(f[i-1][j-1]+(p[i]==q[j]),max(f[i][j-1],f[i-1][j]));

return f[lp][lq];

}


int main(void)

{

scanf("%d%s",&ls,s);

for (int i=0;i<=ls;i++) res=max(res,get(i,ls-i));

printf("%d\n",ls-res*2);

return 0;

}

【回顾】

[1] 转化思想:①字母与数的相互转化  ②树与序列的相互转化  ③环与序列的相互转化

[2] 对于字符串的问题,如最长公共子串,还有DP的方法解决

[3] 无后效性的判定  ①位置的单向变化  ②数字的单调变化  ③树结构  ④下标的单调变化(匹配)

[4] 解决问题:①类比   ②简单-特殊化  ③分析对偶问题(最大-最小问题等)


0 0
原创粉丝点击