给了一个串,求最少填几个字母可以组成回文串,我们发现找到最中间的数后,其余只要不对称的都需要补(左边的补到右边,右边的补到左边所以=len-中间相同的子串),所以不如去求中间的子串,一减就可以了。
string:len=s1.size();
char:len=strlen();
从一开始录入:scanf("%s",s1+1);
从下标一开始计数:int len=strlen(s1+1);
既然是回文串,左右相同,就可以直接求它倒过来和它的最大公共子序列。
但当s1[i]==s2[j]时,是可以直接继承然后+1的;
如
Adb3bdmzA
Azmdb3bdA
最边上的A也是不用补的,
最长公共子序列如下:
#include <bits/stdc++.h> using namespace std; int n,a[1000008],b[10000008],f[10008][10008]; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) scanf("%d",&b[i]); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ if(a[i-1]==b[j-1]) f[i][j]=max(f[i][j],f[i-1][j-1]+1); else f[i][j]=max(f[i-1][j],f[i][j-1]); } int ans=f[n][n]; printf("%d",ans); return 0; }
而本题的代码如下:
#include <iostream> #include <cstdio> #include <cstring> using namespace std; char s1[1009],s2[1009]; int f[1009][1009],maxn; int main(){ scanf("%s",s1+1); int len=strlen(s1+1); for(int i=1;i<=len;i++) s2[len-i+1]=s1[i]; for(int i=1;i<=len;i++){ for(int j=1;j<=len;j++){ if(s1[i]==s2[j]) f[i][j]=max(f[i][j],f[i-1][j-1]+1); else f[i][j]=max(f[i-1][j],f[i][j-1]); //maxn=max(maxn,f[i][j]); } } printf("%d",len-f[len][len]); return 0; }
打个黄题打的我快不想学了,状态转移方程还是不会列。