dp中的经典例题


求最长回文字符串(马拉车算法)

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll int maxn = 3e7+10;
const ll int N = 4e6+10;
#define bug(x) cout<<#x<<" == "<<x<<endl;
int p[maxn] = { 0 };
///以i为中心的最大回文字符串(此时的字符串是处理过的)到左端点的距离 + 1
int id=0;///当前计算的最大长度的字符串的中心
int maxx=0;///以id为中心的最大回文字符串(此时的字符串是处理过的)的右端点+1
///求最大回文串
int main()
{
    string a;
    string b;
    cin>>a;
    b += '$';
    for(int i=0;i<a.size();i++)
    {
        b += '#';
        b += a[i];
    }
    b += '#';
    int len=b.length();
    ///预处理,将每一个字符串变成奇数串 使子串的中心固定
    int ans=0;
    int pos=2;
    for(int i=1;i<len;i++)
    {
        if(maxx>i)
        {
            p[i] = min(maxx-i,p[2*id-i]);
            ///当maxx>i的时候 说明 以id为中心,左右两端长度为maxx-id的字符串里面包含了b[i];
            ///说明 id-(i-id)和b[i]是这个字符串里面两个对称点,
            ///而且i-(i-maxx)~maxx部分也和2*id-maxx~2*id-i+(i-maxx)相同
            ///所以如果p[2*id-1]<=maxx-i -> p[i]==p[2*id-1];
            ///如果p[2*id-1]>maxx-i,只能截取肯定相同的部分即maxx-i;
        }
        else
        {
            p[i] = 1;
        }
        while(b[ i-p[i] ] ==b[ i+p[i] ] )
        {
            p[i]++;
        }
        if(i+p[i]>maxx)
        {
            maxx = i + p[i];
            id = i;
        }
        if(ans<p[i]-1)
        {
            pos=i;
            ans=p[i]-1;
        }
    }
    printf("%d\n",ans);
    ///cout<<(pos/2-1);///最长回文字符串的中心位置
    for(int i=pos/2-1-ans/2;i<=pos/2-1+ans/2;i++)
    {
        cout<<a[i];
    }
}

文章作者: Ximena
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Ximena !
  目录