k-palindrome

Question:

A k-palindrome is a string which transforms into a palindrome on removing at most k characters.

Given a string S, and an interger K, print “YES” if S is a k-palindrome; otherwise print “NO”.
Constraints:
S has at most 20,000 characters.
0<=k<=30

Sample Test Case#1:
Input – abxa 1
Output – YES
Sample Test Case#2:
Input – abdxa 1
Output – No

one solution:
Let's say p[n] is a palindrom with lenght n. Let l will be begining, end e the end of a palindrom. Then we can see that:
1) p[l] == p[h], then we need to check p[l+1] == p[h – 1], i.e abcba, where p[l] == a == p[h]
2a) p[l] != p[h], then we need to check p[l+1],p[h] (we removed p[l])
2b) p[l] != p[h], then we need to check p[l], p[h-1], (we removed p[h])

bool isKPalindrom(string input, int k)
{
        int answers[input.size() + 1][input.size() + 1];
        int N = input.size();
        for(int i = 0; i <= N; i++)
                for(int j = 0; j <= N; j++)
                        answers[i][j] = 0;


        for(int gap = 1; gap <= N; gap++)
        {
                int l = 1;
                int h = l + gap;
                for(; h <= N; l++, h++)
                {
                        if(input[l-1] == input[h - 1])
                                answers[l][h] = answers[l+1][h-1];
                        else
                                answers[l][h] = 1 + min(answers[l+1][h], answers[l][h-1]);
                }
        }

        return answers[1][N] <= k;
}

 

The complexity is O(n^2).

Another solution:

The question asks if we can transform the given string S into its reverse deleting at most K letters.
We could modify the traditional Edit-Distance algorithm, considering only deletions, and check if this edit distance is <= K. There is a problem though. S can have length = 20,000 and the Edit-Distance algorithm takes O(N^2). Which is too slow.

(From here on, I'll assume you're familiar with the Edit-Distance algorithm and its DP matrix)

However, we can take advantage of K. We are only interested *if* manage to delete K letters. This means that any position more than K positions away from the main diagonal is useless because its edit distance must exceed those K deletions.

Since we are comparing the string with its reverse, we will do at most K deletions and K insertions (to make them equal). Thus, we need to check if the ModifiedEditDistance is <= 2*K
Here's the code:

int kpalindrome(string &a, int k){
    int asize = a.size();
    string b = a;
    reverse(b.begin(), b.end());
    int bsize = asize;
    vector<vector<int> > dp(asize+1, vector<int>(bsize+1, 1000));
    for(int i = 0; i <= asize; i++){
        dp[i][0] = i;
		dp[0][i] = i;
    }
        
    for(int i = 1; i <= asize; i++){
        for(int j = max(1, i-k); j <= min(bsize, i+k); j++){
            if(a[i-1] == b[j-1]){
                dp[i][j] = dp[i-1][j-1];
            }
            dp[i][j] = min(dp[i][j], dp[i-1][j]+1);
            dp[i][j] = min(dp[i][j], dp[i][j-1]+1);
        }
    }
    if(dp[asize][bsize]<= 2*k)    return dp[asize][bsize];
    else return -1;
}

int _tmain(int argc, _TCHAR* argv[])
{
	string a = "abxa";
	int ret = kpalindrome(a, 1);
	cout<<ret<<endl;
	return 0;
}

 

We only process 2*K+1 columns per row. So this algorithm works in O(N*K) which is fast enough.

 

From:

https://linzhongzl.wordpress.com/2013/11/25/k-palindrome/

你可能感兴趣的:(k-palindrome)