繁体   English   中英

如何检查字符串是否以回文开头?

[英]How to check if a string start with a palindrome?

我想检查一个字符串是否以回文子字符串开头; 我正在寻找最长的回文子字符串,该子字符串从数组的开头开始。 这是O(n*n)的简单方法。 有没有更聪明的方法?

//not safe for empty string
bool isPalindrome(string s)
{
    string rev = s;
    std::reverse(rev.begin(), rev.end());
    return rev == s;
}

int startWithPalindome(const string a)
{
    int N = a.length();
    for (int len = N; len > 0; len--)
    {
        bool isPal = isPalindrome(a.substr(0,len));
        if (isPal)
            return len;
    }

    return -1;
}

编辑:澄清:我知道此代码可以通过多种方式进行改进,可以进行多种调整,但是我对减少渐近时间的复杂度感兴趣。

优化startWithPalindrome()

您的方法是寻找可能的最大回文,并使用蛮力依次减小您考虑的子字符串的大小,直到找到回文。

您可以轻松地进行大量比较,方法不是从字符串的总大小开始,而是使用rfind()第一个字符的最后出现位置。 然后,您可以向后迭代到该字符的先前位置,依此类推:

int startWithPalindome(const string a)
{
    if (a.length()>1)
    {
        for (int N = a.rfind(a[0]); N!=string::npos && N>0; N= a.rfind(a[0],N-1) ) {
            if ( isPalindrome(a.substr(0,N+1)) )
                return N+1;
        }
    }
    return -1;
}

顺便说一句:isPalindrome()的优化

您的isPalindrom()版本将空字符串或单个字符串视为回文。 您可以保持这种状态,但是我建议消除这种情况。

尽管如此,我还是建议您使用一个小的变体,它不复制字符串,而只是从头到尾进行遍历,因此(几乎)执行最少的操作:

bool isPalindrome(string s)
{
    if (s.length()<2)       // empty strings and singles chars are no palindromes !
        return false;   
    for (auto f=s.cbegin(), r=s.cend()-1; f!=r;  r--) {
        if (*f!=*r)         // if the nth letter from start doesn't match nth from ens
            return false;        // not a palindrom
        if (++f==r)         // if middle of string is between two chars
            break;     
    }
    return true;            // we meet in the middle so it's a palindrome 
}

在线演示

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM