POJ 1159 Palindrome 迴文子序列

1. http://poj.org/problem?id=1159

題意:給定一個字符串,求最少插入多少字符使該字符串變成迴文字符串。

分析:

方法1:先求該字符串與其逆序列的最長公共子序列LCS(該部分已經迴文),則原字符串長度減去LCS長度即爲需要插入的字符數。

方法2::(算法導論習題15.2 最長迴文子序列)

i=j時,LPS(i,j)=1;i<j時,LPS(i,j)=0;

以“BBABCBCAB”爲例

#include<iostream>
#include<string>
using namespace std;
const int maxn=5005;
int dp[2][maxn];//滾動數組 
string str;
int main()
{
	int n;
	cin>>n;
	cin>>str;
	for(int i=n-1;i>=0;i--)
	{
		dp[i&1][i]=1;
		for(int j=i+1;j<n;j++)
			if(str[i]==str[j])
				dp[i&1][j]=dp[(i+1)&1][j-1]+2;
			else
				dp[i&1][j]=max(dp[i&1][j-1],dp[(i+1)&1][j]);
	}
	
	cout<<n-dp[0][n-1]<<endl;
	return 0;
}
//輸出最長迴文子序列
void Printlps(string str, int m, int n)
{
	if (m == n)
	{
		cout << str[m]; return;
	}
	if (str[m] == str[n])
	{
		cout << str[m];
		Printlps(str, m + 1, n - 1);
		cout << str[n];
	}
	else if (dp[m][n - 1] >= dp[m + 1][n])
		Printlps(str, m, n - 1);
	else Printlps(str, m + 1, n);
}

最長迴文子串

①動態規劃:

 

#include<iostream>  
#include<string>  
#include<algorithm>  
using namespace std;
const int maxn = 100;
bool dp[maxn][maxn] = { 0 };

int lps(string str)
{
	memset(dp, false, sizeof(dp));
	int result = 0;
	for (int i = str.length() - 1; i >= 0; i--)//i爲起點
	{
		dp[i][i] = true;
		for (int j = i + 1; j < str.length(); j++)//j爲終點
		{
			if ((j == i + 1 || dp[i + 1][j - 1]) && str[i] == str[j])
			{
				dp[i][j] = true;
				result = max(result, j - i + 1);
			}
		}
	}
	return result;
}

int main()
{
	string str;
	cin >> str;
	int res = lps(str);
	cout << res << endl;
	getchar();
	return 0;
}

 

 

 

Manacher算法:見分析

#include<iostream>  
#include<string>  
#include<algorithm>  
using namespace std;
const int maxn = 100;

int p[maxn];
char s[maxn];

int Init(string str)
{
	s[0] = '$'; s[1] = '#';
	for (int i = 0,j=2; i < str.length(); i++)
	{
		s[j++] = str[i];
		s[j++] = '#';	
	}
	return str.length() * 2 + 2;
}
int Manacher(string str)
{
	int len = Init(str);
	int Maxlen = 0, MaxRight = 0, pos = 0;
	for (int i = 1; i < len; i++)
	{
		p[i] = i < MaxRight ? min(p[2 * pos - i], MaxRight - i) : 1;
		while (s[i - p[i]] == s[i + p[i]]) p[i]++; //以i爲中心擴展
		if (i + p[i] > MaxRight)//更新MaxRight,pos
		{
			MaxRight = i + p[i];
			pos = i;
		}
		Maxlen = max(Maxlen, p[i]-1);
	}
	return Maxlen;
}

int main()
{
	string str;
	cin >> str;;
	int ans=Manacher(str);
	cout << ans << endl;
	getchar();
	return 0;
}

 

 

 

 

 

 

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