[poj3974] Palindrome 解题报告 (hash\manacher)

题目链接:http://poj.org/problem?id=3974

题目:

多组询问,每组给出一个字符串,求该字符串最长回文串的长度

数据范围支持$O(nlog n)$

解法一:

二分+hash

回文串分奇数串和偶数串。对于奇数串,我们枚举它的中点,二分一下这个中点可以向两边扩展多远的距离;对于偶数串,我们枚举它中间两个点靠左的点,同样二分可以扩展的距离,这样时间复杂度就是$O(nlog n)$的了

说起来容易,写起来不是很容易

解法二:

每次跑一遍manacher就好了

说起来容易,写起来也很容易

解法一代码:

#include<algorithm>
#include<cstring>
#include<iostream>
#include<cstdio>
typedef unsigned long long ull;
using std::string;
using std::cin;
using std::max;
using std::min;

const int N=1e6+15;
int cas,ans;
ull p[N],f[N],d[N];
string ch;
int main()
{
    p[0]=1;
    for (int i=1;i<=N;i++) p[i]=p[i-1]*113;
    while (cin>>ch)
    {
        if (ch=="END") break;
        printf("Case %d: ",++cas);
        memset(f,0,sizeof(f));
        memset(d,0,sizeof(d));
        int n=ch.size();
        for (int i=0;i<n;i++)
        {
            f[i+1]=f[i]*113+ch[i]-‘a‘+1;
        }
        for (int i=n;i>=1;i--)
        {
            d[i]=d[i+1]*113+ch[i-1]-‘a‘+1;
        }
        ans=0;
        for (int i=1;i<=n;i++)
        {
            int l=1,r=min(i,n-i+1);
            while (l<r)
            {
                int mid=l+r>>1;
                int L1=i-mid+1,R1=i;
                int L2=i,R2=i+mid-1;
                int tmp1=f[R1]-f[L1-1]*p[R1-L1+1],tmp2=d[L2]-d[R2+1]*p[R2-L2+1];
                if (tmp1==tmp2) l=mid+1;
                else r=mid;
            }
            int L1=i-l+1,R1=i;
            int L2=i,R2=i+l-1;
            int tmp1=f[R1]-f[L1-1]*p[R1-L1+1],tmp2=d[L2]-d[R2+1]*p[R2-L2+1];
            if (tmp1!=tmp2) l--;
            ans=max(ans,2*l-1);

            l=1,r=min(i,n-i);
            while (l<r)
            {
                int mid=l+r>>1;
                int L1=i-mid+1,R1=i;
                int L2=i+1,R2=i+1+mid-1;
                int tmp1=f[R1]-f[L1-1]*p[R1-L1+1],tmp2=d[L2]-d[R2+1]*p[R2-L2+1];
                if (tmp1==tmp2) l=mid+1;
                else r=mid;
            }
            L1=i-l+1,R1=i;
            L2=i+1,R2=i+1+l-1;
            tmp1=f[R1]-f[L1-1]*p[R1-L1+1],tmp2=d[L2]-d[R2+1]*p[R2-L2+1];
            if (tmp1!=tmp2) l--;
            ans=max(ans,2*l);
        }
        printf("%d\n",ans);
    }
    return 0;
}

解法二代码:

#include<algorithm>
#include<cstdio>
#include<cstring>
#include<iostream>

const int N=2e6+15;
using std::string;
using std::cin;
using std::min;
using std::max;
string ch;
char s[N];
int hw[N];
int main()
{
    int cas=0;
    while (cin>>ch)
    {
        if (ch=="END") return 0;
        printf("Case %d: ",++cas);
        int n=ch.size();
        memset(hw,0,sizeof(hw));
        s[0]=s[1]=‘#‘;
        for (int i=1;i<=n;i++)
        {
            s[i<<1]=ch[i-1];
            s[i<<1|1]=‘#‘;
        }
        n=n*2+2;
        s[n]=0;
        int mx=0,mid;
        for (int i=1;i<n;i++)
        {
            if (i<mx) hw[i]=min(mid+hw[mid]-i,hw[(mid<<1)-i]);
            else hw[i]=1;
            for (;s[i+hw[i]]==s[i-hw[i]];hw[i]++);
            if (hw[i]+i>mx)
            {
                mx=hw[i]+i;
                mid=i;
            }
        }
        int ans=1;
        for (int i=1;i<n;i++) ans=max(ans,hw[i]);
        printf("%d\n",ans-1);
    }
    return 0;
} 

原文地址:https://www.cnblogs.com/xxzh/p/9683597.html

时间: 2024-10-14 13:50:12

[poj3974] Palindrome 解题报告 (hash\manacher)的相关文章

LeetCode: Valid Palindrome 解题报告

Valid Palindrome Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. For example,"A man, a plan, a canal: Panama" is a palindrome."race a car" is not a palindrome. Note:Have you

leetCode解题报告5道题(九)

题目一:Combinations Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. For example,If n = 4 and k = 2, a solution is: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ] 分析: 题意给我们一个数字n, 和一个数字k,让我们求出从 1~~n中取出k个数所能得到的组合数 所

pat解题报告【1078】

1078. Hashing (25) 时间限制 100 ms 内存限制 32000 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue The task of this problem is simple: insert a sequence of distinct positive integers into a hash table, and output the positions of the input numbers.  The hash fun

2014 UESTC暑前集训数据结构专题解题报告

A.Islands 这种联通块的问题一看就知道是并查集的思想. 做法:从高水位到低水位依序进行操作,这样每次都有新的块浮出水面,可以在前面的基础上进行合并集合的操作.给每个位置分配一个数字,方便合并集合.同时将这些数字也排一个序,降低枚举的复杂度.合并集合时向四周查询浮出水面但是没有合并到同一集合的点进行合并. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath&

poj分类解题报告索引

图论 图论解题报告索引 DFS poj1321 - 棋盘问题 poj1416 - Shredding Company poj2676 - Sudoku poj2488 - A Knight's Journey poj1724 - ROADS(邻接表+DFS) BFS poj3278 - Catch That Cow(空间BFS) poj2251 - Dungeon Master(空间BFS) poj3414 - Pots poj1915 - Knight Moves poj3126 - Prim

[LeetCode]LRU Cache, 解题报告

题目 Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set. get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.

NOIP2008解题报告

2008年的题目相对比较简单,都不是很麻烦,认真写就能写对. 第一题: 题目大意:给出一个小写单词,求出最少出现的字母的出现次数和最多出现的字母的出现次数. 解题过程:直接hash模拟就好. 第二题: 给你n根火柴棍,你可以拼出多少个形如“A+B=C”的等式?等式中的A.B.C是用火柴棍拼出的整数(若该数非零,则最高位不能是0).用火柴棍拼数字0-9的拼法如图所示: 注意: 1. 加号与等号各自需要两根火柴棍 2. 如果A≠B,则A+B=C与B+A=C视为不同的等式(A.B.C>=0) 3. n

NOIP2009解题报告

09年的题总体来说 没有难题,但是每道题除了第一题都要认真的慢慢写才能AC, 第一题: R国和S国正陷入战火之中,双方都互派间谍,潜入对方内部,伺机行动. 历经艰险后,潜伏于S国的R国间谍小C终于摸清了S国军用密码的编码规则:1. S国军方内部欲发送的原信息经过加密后在网络上发送,原信息的内容与加密后所的内容均由大写字母‘A’—‘Z’构成(无空格等其他字母).2. S国对于每个字母规定了对应的“密字”.加密的过程就是将原信息中的所有字母替换为其对应的“密字”.3. 每个字母只对应一个唯一的“密字

人生第一场CTF的解题报告(部分)

解题报告 濮元杰部分: 王者归来: 120 场景 小王入职了一段时间,最近有点无聊.Web安全项目不多,白天看着其他项目组的同事忙得热火朝天,小王有点坐不住了,这也许是新人都会有的想法,乐于助人.想到这,小王一眼看到了隔壁的小丽,哎,IT界小丽绝对算得上是一位美女啦,于是小王凑了过去对小丽说:小丽,看你眉头紧锁的,需要本大侠帮忙吗?小丽转头看着小王,愣了足足有10秒,突然说:那,那好吧,如果你帮我搞定这三个问题,嗯~我请你吃晚饭,就我们两个.天哪,这,这,小王已经按耐不住突如其来的喜悦,战斗力倍