pku1159 Palindrome DP

有一個感悟就是一大羣人指着錯的東西硬說是對的= =

MLE後想了下答案最大也就5000,然後改成short int 就可以了,A掉之後翻了下discuss,然後看到了一條定理:答案是長度減去與反串的最長公共子串= =當時我就懵逼了趕快手寫了一組數據發現是錯的,然而似乎子序列就對了

然後我點開回復一條一條的看看到一條這樣的:

哥/姐,最長子列不要連續地.........
大俠連最長公共子序列都沒搞懂。。
雖然這是一條2011年的評論但是我還是回了一句,既然你知道是子序列那你說lz是對的?

一臉懵逼

好吧現在我知道了兩種做法,一種是像之間的DNA配對的PKU1141那樣當作增加一個字符默認與另外一個字符匹配那樣的類似區間DP的寫法

一種是求出原串與反串的最長公共子序列長度再用原串長度減去即爲答案,證明其實也很簡單,腦補一下就好惹,都是N2的

還有聽說滾動數組能有很大優化?然後再動態一下就更小了?

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define LL long long
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define down(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
inline LL read()
{
	LL d=0,f=1;char s=getchar();
	while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
	while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
	return d*f;
}
#define N 5005
#define inf 65534
char s[N];
unsigned short int f[N][N];
int n;

int dfs(int i,int j)
{
	if(i>j)return f[i][j]=0;
	if(f[i][j]!=inf)return f[i][j];
	if(s[i]==s[j])
	{
		int ret=dfs(i+1,j-1);
		f[i][j]=ret;
	}else
	{
		int ret1=dfs(i+1,j);
		int ret2=dfs(i,j-1);
		f[i][j]=min(ret1,ret2)+1;
	}
	return f[i][j];
}

int main()
{
	n=read();
	fo(i,1,n)fo(j,1,n)f[i][j]=inf;
	fo(i,1,n)s[i]=getchar();
	cout<<dfs(1,n)<<endl;
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章