Самый длинный префикс палиндрома - PullRequest
4 голосов
/ 30 сентября 2010

Как найти самый длинный палиндромный префикс строки в O (n)?

Ответы [ 3 ]

6 голосов
/ 30 сентября 2010

Используйте катящийся хеш . Если a - ваша строка, пусть ha[x] будет хэш первых x символов в a, вычисленных слева направо, и пусть hr[x] будет хэш первых x символов в s вычисляется справа налево. Вы заинтересованы в последней позиции i, для которой hf[i] = hb[i].

Код в C (используйте два хэша для каждого направления, чтобы избежать ложных срабатываний):

int match = n - 1;

int ha1 = 0, ha2 = 0, hr1 = 0, hr2 = 0;
int m1 = 1, m2 = 1;
for ( int i = 0; a[i]; ++i )
{
    ha1 = (ha1 + m1*a[i]) % mod1;
    ha2 = (ha2 + m2*a[i]) % mod2;

    hr1 = (a[i] + base1*hr1) % mod1;
    hr2 = (a[i] + base2*hr2) % mod2;

    m1 *= base1, m1 %= mod1;
    m2 *= base2, m2 %= mod2;

    if ( ha1 == hr1 && ha2 == hr2 )
        match = i;
}
1 голос
/ 30 сентября 2010

Решение для более общей проблемы, не префикса, а подстроки, в O (n):

http://www.akalin.cx/2007/11/28/finding-the-longest-palindromic-substring-in-linear-time/

Второй результат в Google для "самого длинного префикса палиндрома" ....

Или решение с использованием суффикс-деревьев:

http://www.allisons.org/ll/AlgDS/Tree/Suffix/

0 голосов
/ 12 июня 2019

Использование z-алгоритма (https://codeforces.com/blog/entry/3107). Предположим, s - заданная строка длины m. Код:

    string rev="",str=s;
    int m=s.size(),longestPalindromicPrefix=1;
    if(m==0 || m==1)    longestPalindromicPrefix=m; 
    for(int i=m-1;i>=0;i--)
        rev+=s[i];
    s+='#';
    s+=rev;
    int n=s.size(),z[n+4],l=0,r=0;
    for(int i=1;i<n;i++){
        if(i>r){
            l=r=i;
            while(r<n && s[r-l]==s[r])
                r++;
            z[i]=r-l,r--;
        }
        else{
            int k=i-l;
            if(z[k]<r-i+1)
                z[i]=z[k];
            else{
                l=i;
                while(r<n && s[r-l]==s[r])
                    r++;
                z[i]=r-l,r--;
            }
        }
    }

    for(int i=m+1;i<n;i++){
        if(2*z[i]>=2*m-i && z[i]>longestPalindromicPrefix)
            longestPalindromicPrefix=z[i];
    }
...