Palindrome

  • O(n^2)的DP是显然的,但没有优化思路。考虑证伪数据范围。发现n>2600时,根据抽屉原理,一定有一个字符出现了至少101次。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
int f[3005][3005];
int g[3005][3005];
char s[50005];
int cnt[30],pi,pj;
string tmp="";
void solve(int maxn)
{
	string ans1="";
	while(ans1.size()<maxn)
	{
		if(g[pi][pj]==3)
		{
			ans1+=s[pi];
			pi--;
			pj++;
		}
		else if(g[pi][pj]==2)
		{
			pj++;
		}
		else
		{
			pi--;
		}
	}
	string ans2=ans1;
	reverse(ans1.begin(),ans1.end());
	cout<<ans1<<tmp<<ans2<<endl;
}
int main()
{
	string t;
	cin>>t;
	int n=t.size();
	if(n>=2600)
	{
		for(int i=0;i<n;i++)
		{
			cnt[t[i]-'a']++;
			if(cnt[t[i]-'a']>=100)
			{
				for(int j=0;j<100;j++)
				{
					cout<<t[i];
				}
				cout<<endl;
				return 0;
			}
		}
	} 
	for(int i=1;i<=n;i++)
	{
		s[i]=t[i-1];
	}
	pi=0,pj=n+1;
	for(int i=1;i<=n;i++)
	{
		for(int j=n;j>=i+1;j--)
		{
			if(f[i-1][j]>f[i][j+1])
			{
				f[i][j]=f[i-1][j];
				g[i][j]=1;
			}
			else
			{
				f[i][j]=f[i][j+1];
				g[i][j]=2;
			}
			if(s[i]==s[j]&&f[i-1][j+1]+1>f[i][j])
			{
				f[i][j]=f[i-1][j+1]+1;
				g[i][j]=3;
			}
			if(f[i][j]>f[pi][pj]||f[i][j]==f[pi][pj]&&j-i>pj-pi)
			{
				pi=i;
				pj=j; 
			}
			if(f[i][j]==50)
			{
				pi=i;
				pj=j;
				solve(50);
				return 0;
			}
		}
	}
	int maxn=f[pi][pj];
	if(pj!=pi+1)
	{
		tmp+=s[pi+1];
	}
	solve(maxn);
	return 0;
}
posted @ 2024-07-24 19:35  D06  阅读(3)  评论(0编辑  收藏  举报