最长的独特回文

时间:2017-08-14 17:43:33

标签: c# algorithm

我有以下界面

public interface IPalindromeEngine
{
    Palindrome GetLongestPalindrome(string sequence);

    Task<Palindrome> GetLongestPalindromeAsync(string sequence);

    List<Palindrome> GetLongestPalindromes(string sequence, int n, bool uniqueOnly);

    Task<List<Palindrome>> GetLongestPalindromesAsync(string sequence, int n, bool uniqueOnly);
}

http://www.leetcode.com/2011/11/longest-palindromic-substring-part-ii.html实施代码似乎经过充分测试(来自所有评论者和实施者)......

/// <summary>
/// Computes the longest palindromic substring in linear time
/// using Manacher's algorithm.
///
/// The code is lifted from the following excellent reference
/// http://www.leetcode.com/2011/11/longest-palindromic-substring-part-ii.html
/// </summary>
public class ManacherPalindromeEngine : IPalindromeEngine
{
    // p[i] = length of longest palindromic substring of transform, centered at i.
    private int[] p;
    private char[] transform;
    private string sequence;

    private void Initialize()
    {
        transform = new char[sequence.Length * 2 + 3];
        transform[0] = '$';
        transform[sequence.Length * 2 + 2] = '@';
        for (int i = 0; i < sequence.Length; ++i)
        {
            transform[2 * i + 1] = '#';
            transform[2 * i + 2] = sequence[i];
        }
        transform[sequence.Length * 2 + 1] = '#';
    }

    private void ExtractPalindromesViaManacher(string sequence)
    {
        this.sequence = sequence;
        Initialize();

        int center = 0, right = 0;
        p = new int[transform.Length];
        for (int i = 1; i < transform.Length - 1; i++)
        {
            int mirror = 2 * center - i;

            if (right > i)
                p[i] = Math.Min(right - i, p[mirror]);

            // Attempt to expand palindrome centered at i.
            while (transform[i + (1 + p[i])] == transform[i - (1 + p[i])])
                p[i]++;

            // If palindrome centered at i expands past right,
            // adjust center based on expanded palindrome.
            if (i + p[i] > right)
            {
                center = i;
                right = i + p[i];
            }
        }
    }

    public Palindrome GetLongestPalindrome(string sequence)
    {
        if (String.IsNullOrEmpty(sequence))
            return null;

        ExtractPalindromesViaManacher(sequence);

        int length = 0;
        int center = 0;
        for (int i = 1; i < p.Length - 1; ++i)
        {
            if (p[i] > length)
            {
                length = p[i];
                center = i;
            }
        }
        int startIndex = (center - 1 - length) / 2;
        string s = this.sequence.Substring(startIndex, length);
        return new Palindrome(s, startIndex);
    }

    public Task<Palindrome> GetLongestPalindromeAsync(string sequence)
    {
        return Task.Run(() => GetLongestPalindrome(sequence));
    }

    public List<Palindrome> GetLongestPalindromes(string sequence, int n, bool uniqueOnly)
    {
        if (String.IsNullOrEmpty(sequence))
            return null;

        ExtractPalindromesViaManacher(sequence);

        List<Palindrome> palindromes = null;
        if (uniqueOnly)
        {
            palindromes = p
                .Select((l, i) => new { Length = l, Index = i })
                .OrderByDescending(c => c.Length)
                .Select(c =>
                {
                    int startIndex = (c.Index - 1 - c.Length) / 2;
                    string s = this.sequence.Substring(startIndex, c.Length);
                    Trace.WriteLine(startIndex);
                    return new Palindrome(s, startIndex);
                })
                .ToList();
            palindromes = palindromes
                .Distinct(new Palindrome.DuplicateComparer())
                .Take(n)
                .ToList();
        }
        else
        {
            palindromes = p
                .Select((l, i) => new { Length = l, Index = i })
                .OrderByDescending(c => c.Length)
                .Take(n)
                .Select(c =>
                {
                    int startIndex = (c.Index - 1 - c.Length) / 2;
                    string s = this.sequence.Substring(startIndex, c.Length);
                    Trace.WriteLine(startIndex);
                    return new Palindrome(s, startIndex);
                })
                .ToList();
        }
        return palindromes;
    }

    public Task<List<Palindrome>> GetLongestPalindromesAsync(string sequence, int n, bool uniqueOnly)
    {
        return Task.Run(() => GetLongestPalindromes(sequence, n, uniqueOnly));
    }
}

public class Palindrome
{
    public Palindrome(string sequence, int startIndex)
    {
        Sequence = sequence;

        if (startIndex < 0)
            throw new ArgumentException("startIndex must be >= 0");
        StartIndex = startIndex;
    }

    public int StartIndex { get; set; }

    public int Length
    {
        get
        {
            if (String.IsNullOrEmpty(Sequence))
                return 0;
            return Sequence.Length;
        }
    }

    public string Sequence { get; }

    internal class DuplicateComparer : IEqualityComparer<Palindrome>
    {
        public bool Equals(Palindrome x, Palindrome y)
        {
            return x.Sequence == y.Sequence;
        }

        public int GetHashCode(Palindrome obj)
        {
            unchecked 
            {
                int hash = 17;
                return hash * 23 + obj.Sequence.GetHashCode();
            }
        }
    }
}

现在我已经在一些测试案例中对此进行了测试,但有一个案例似乎不对。那是输入字符串

  

“weeewweeew”

返回结果:

  1. weeewweeew开始:0长度:10
  2. weeew开始:0长度:5
  3. ee开始:1长度:2

  4. 为什么我没有收到字符串“eeewweee”或“eee”?

  5. 有关代码质量的任何其他建议将不胜感激。

1 个答案:

答案 0 :(得分:1)

/myService/clubs/{ClubId}/person/{PersonId}

此时,对于字符串中的每个位置,查询都包含以该位置为中心的最长回文的长度。为了检索所有回文,你需要选择具有相同中心的所有回文的子串:

palindromes = p
    .Select((l, i) => new { Length = l, Index = i })
    .OrderByDescending(c => c.Length)