• Manacher算法求回文半径


    http://wenku.baidu.com/link?url=WFI8QEEfzxng9jGCmWHoKn0JBuHNfhZ-tKTDMux34CeY8UNUwLVPeY5HA3TyoKU2XegXFPifjunarW-YmXFrP_m8-3DEhBu1MHxHghHqD0O

    这篇讲的比较好,准备一个模板,做题的时候用。

    void manacher()
    {
        int mx = 0, id = 0;
        for (int i = 1; i <= n; i++)
        {
            if (mx > i)
                p[i] = min(p[id * 2 - i], mx - i);
            else
                p[i] = 1;
            while (a[i + p[i]] == a[i - p[i]])
                p[i]++;
            if (mx < p[i] + i)
            {
                mx = p[i] + i;
                id = i;
            }
        }
    }

    这个初始化的时候是从1开始的

    for (int i = 1; i <= n; i++)
    {
                a[i * 2 - 1] = str[i]; 
                a[i * 2] = -1;
    }

    其中p表示回文半径,str是原串,a表示添加字符之后的串

    两个例题:

    hdu5340

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    #include <algorithm>
    
    using namespace std;
    typedef long long LL;
    const int maxn = 20010;
    char str[maxn], a[maxn<<1];
    int p[maxn<<1], L[maxn<<1], R[maxn<<1];
    int n;
    void manacher()
    {
        int mx = 0, id = 0;
        for (int i = 1; i <= n; i++)
        {
            if (mx > i)
                p[i] = min(p[id * 2 - i], mx - i);
            else
                p[i] = 1;
            while (a[i + p[i]] == a[i - p[i]])
                p[i]++;
            if (mx < p[i] + i)
            {
                mx = p[i] + i;
                id = i;
            }
        }
    }
    bool solve()
    {
        for (int i = 1; i <= L[0]; i++)
        {
            for (int j = 1; j <= R[0]; j++)
            {
                int l = L[i] + 1;
                int r = R[j] - 1;
                if (r - l <= 0)
                    continue;
                int mid = (l + r) / 2;
                if (p[mid] >= r - mid + 1)
                    return true;
            }
        }
        return false;
    }
    int main()
    {
        int T;
        scanf("%d", &T);
        while (T--)
        {
            scanf("%s", str + 1);
            n = strlen(str + 1);
            for (int i = 1; i <= n; i++)
            {
                a[i * 2 - 1] = str[i]; 
                a[i * 2] = '#';
            }
            n = n * 2 - 1;
            a[0] = '$';
            a[n + 1] = '@';
            manacher();
            memset(L, 0, sizeof(L));
            memset(R, 0, sizeof(R));
            for (int i = 1; i <= n; i++)
            {
                int l = i - p[i] + 1;
                int r = i + p[i] - 1;
                if (l == 1)
                    L[++L[0]] = r;
                if (r == n)
                    R[++R[0]] = l;
            }
            if (solve())
                puts("Yes");
            else
                puts("No");
        }
        return 0;
    }
    View Code

    hdu5371

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    #include <algorithm> 
    using namespace std;
    typedef long long LL;
    const int maxn = 100010;
    int str[maxn], a[maxn<<1];
    int p[maxn<<1];
    int n;
    void manacher()
    {
        int mx = 0, id = 0;
        for (int i = 1; i <= n; i++)
        {
            if (mx > i)
                p[i] = min(p[id * 2 - i], mx - i);
            else
                p[i] = 1;
            while (a[i + p[i]] == a[i - p[i]])
                p[i]++;
            if (mx < p[i] + i)
            {
                mx = p[i] + i;
                id = i;
            }
        }
    }
    void print()
    {
        for (int i = 1; i <= n; i++)
            printf("%d ", p[i]);
    }
    int main()
    {
        int T;
        int kase = 0;
        scanf("%d", &T);
        while (T--)
        {
            scanf("%d", &n);
            for (int i = 1; i <= n; i++)
                scanf("%d", &str[i]);
            for (int i = 1; i <= n; i++)
            {
                a[i * 2 - 1] = str[i]; 
                a[i * 2] = -1;
            }
            int m = n;
            n = n * 2 - 1;
            a[0] = -5;
            a[n + 1] = -8;
            manacher(); 
            int ans = 0;
            for (int i = 2; i <= n; i += 2)
                p[i] /= 2; 
            for (int i = 2; i <= n; i += 2)
            {
                if (p[i] * 3 < ans)
                    continue;
                for (int j = p[i]; j * 3 >= ans; j--)
                {
                    if (p[i + j * 2] >= j)
                    {
                        ans = max(ans, j * 3);
                        break;
                    }
                }
            }
            printf("Case #%d: %d
    ", ++kase, ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    ---Install Oracle Java 11 SE under Ubuntu
    ---个人英语单词收集!
    ---Android alarm使用
    ---FLAG_NO_CREATE 的用途!
    ---Englist Word Memo
    ---Ubuntu安装后要做的几件重要的事情 (适合Ubuntu机子的开发人员)
    ---Android egl/egls 概念
    --- Checking fs of the mounted partitions on Android device
    移动应用论坛——如何“玩赚”微信
    Android复制assets目录下的图片到内存
  • 原文地址:https://www.cnblogs.com/Howe-Young/p/4723203.html
Copyright © 2020-2023  润新知