回文部分文字列(間隔動的計画法)

トピックリンク:22アルゴリズムの設計と分析-動的計画法-仮想裁判官

 

分析:このトピックは比較的単純な間隔動的計画法ですが、長い間私を悩ませていた落とし穴があるので、ここで分析したいと思います

f [i] [j]が、iからjまでの最長の回文部分文字列の長さを表すとします。

私が最初に思ったのは、s [i] == s [j]のとき、s [i]!=の場合、f [i] [j] = f [i + 1][j-1]+2があるということでした。 s[j]はf[i][j] = 0ですが、これは間違っています。i〜jは、s [i] == s [j]だけでなく、i + 1〜jも必要とする回文部分文字列だからです。 -1は回文の部分文字列でもあるため、s [i] == s [j]であることがわかっている場合、f [i] [j] = f [i + 1] [j-1]+2を直接作成することはできません。また、i + 1〜j-1が回文の部分文字列であるかどうかを判断する必要があります。最初は、この状態を判断するのを忘れていたため、waが2回発生しました。もう1つの注意点は、空の文字列も回文の部分文字列であるということです。長さ1のパリンドローム文字列を最初に前処理できます

コードは次のとおりです。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
const int N=1e3+10;
int f[N][N];
char s[N];
int main()
{
	scanf("%s",s+1);
	int l=strlen(s+1),ans=1;
	for(int i=1;i<=l;i++) f[i][i]=1;
	for(int i=1;i<l;i++)
		if(s[i]==s[i+1]) f[i][i+1]=2,ans=2;
	for(int len=3;len<=l;len++)
	for(int i=1;i+len-1<=l;i++)
	{
		int j=i+len-1;
		if((s[j]==s[i])&&(f[i+1][j-1])) f[i][j]=f[i+1][j-1]+2;
		ans=max(ans,f[i][j]);
	}
	cout<<ans;
	return 0;
}

おすすめ

転載: blog.csdn.net/AC__dream/article/details/123906950