given a word,convert it into a pallindrome with minimum addition of letters to it.letters can be added anywhere in the word.for eg if yahoo is given result shud be yahoohay.give a optimize soln
对于题目要多考虑其本身的特殊性质
回文字符串,首尾相同
方法1:
设原字符串是st1
源字符串的反转串是str2
st1和str2的最长公共子序列是st3
接下来就是st1,str2,str3归并的过程。
char* CalcLCS(const char* szStr1, const char* szStr2, char pOut[])
{
assert(szStr2 && szStr1 && pOut);
int nLen1 = strlen(szStr1);
int nLen2 = strlen(szStr2);
if (nLen1 == 0 || nLen2 == 0)
{
pOut[0] = 0;
return pOut;
}
int** pDP = new int*[nLen1];
for (int i = 0; i < nLen1; i++)
pDP[i] = new int[nLen2];
//initialize
bool bMatch = false;
for (int i = 0; i < nLen2; i++)
{
if (bMatch || szStr2[i] == szStr1[0])
{
bMatch = true;
pDP[0][i] = 1;
}
}
bMatch = false;
for (int i = 0; i < nLen1; i++)
{
if (bMatch || szStr1[i] == szStr2[0])
{
bMatch = true;
pDP[i][0] = 1;
}
}
//Calculate lcs length
for (int i = 1; i < nLen1; i++)
{
for (int j = 1; j < nLen2; j++)
{
if (szStr1[i] == szStr2[j])
pDP[i][j] = pDP[i-1][j-1] + 1;
else
pDP[i][j] = pDP[i-1][j] > pDP[i][j-1] ? pDP[i-1][j] : pDP[i][j-1];
}
}
//put string to pOut
int nLCSLen = pDP[nLen1-1][nLen2-1];
int nIter = nLCSLen;
pOut[nIter--] = 0;
int x = nLen1-1;
int y = nLen2-1;
while (nIter >= 0)
{
if (0 == x)
{
pOut[0] = szStr1[0];
break;
}
if (0 == y)
{
pOut[0] = szStr2[0];
break;
}
if (pDP[x][y] == pDP[x-1][y-1]+1 && szStr1[x] == szStr2[y])
{
pOut[nIter--] = szStr1[x];
x--,y--;
}
else if (pDP[x-1][y] == pDP[x][y])
x--;
else y--;
}
for (int i = 0; i < nLen1; i++)
delete []pDP[i];
delete []pDP;
return pOut;
}
char* TurnToPallindrome(const char* szStr, char pOut[])
{
int nLen = strlen(szStr);
char* pLCS = new char[nLen+1];
char* pReverse = new char[nLen+1];
pReverse[nLen] = 0;
int nIter = 0;
for (int i = nLen-1; i >= 0; i--)
pReverse[nIter++] = szStr[i];
CalcLCS(szStr, pReverse, pLCS);
//three way merge
const char* p1 = szStr;
const char* p2 = pLCS;
const char* p3 = pReverse;
char* pWrite = pOut;
while (*p2 != 0)
{
if (*p1 != *p2)
{
*pWrite++ = *p1++;
continue;
}
if (*p3 != *p2)
{
*pWrite++ = *p3++;
continue;
}
*pWrite++ = *p2++;
p1++,p3++;
}
while (*p1 != 0) *pWrite++ = *p1++;
while (*p3 != 0) *pWrite++ = *p3++;
*pWrite = 0;
delete []pLCS;
delete []pReverse;
return pOut;
}
方法2:
如果只让求最少的插入元素的个数,用动态规划,但是要生成回文就比较麻烦了
设f[i][j]表示从i开始的长度为j的字符串变成回文,最小需要插入的元素个数。
如果a[0] = a[n-1]
f[0][n] = f[1][n-2]
否则
f[0][n] = 1 + min(f[0][n-1], f[1][n-1])
#define MAXL 1010
char s[MAXL];
int dp[MAXL][MAXL];
int getPath(int p, int l, char *ans)
{
if(l < 2) {
if(l) *ans = s[p];
return l;
}
if(s[p] == s[p+l-1]) {
*ans = s[p];
return 1+getPath(p+1, l-2, ans+1);
} else if(dp[p][l] == 1+dp[p+1][l-1]) {
*ans = s[p];
return 1+getPath(p+1, l-1, ans+1);
} else {
*ans = s[p+l-1];
return 1+getPath(p, l-1, ans+1);
}
}
int main()
{
char ans[MAXL*2];
cin >> s;
int i, j, l = strlen(s);
for(i = 2; i <= l; i++)
for(j = 0; j <= l-i; j++) {
if(s[j] == s[j+i-1])
dp[j][i] = dp[j+1][i-2];
else
dp[j][i] = 1+min(dp[j+1][i-1], dp[j][i-1]);
}
cout << dp[0][l] << endl;
int len = getPath(0, l, ans);
ans[l+dp[0][l]] = 0;
for(i = l+dp[0][l]-1; i >= len; i--)
ans[i] = ans[l+dp[0][l]-i-1];
cout << ans << endl;
return 0;
}