POJ 3974 Palindrome Manacher

题目大意

给出一个字符串,求出这个字符串的最长回文子串。

思路

前来学习著名的Manacher算法。

这是一个线性时间求出回文子串的算法。具体来说,对于我们弄出的一个回文串,它对于后面的串并不是,没有用的,因为它的左右两侧是相同的,那么自然可以用左边的信息去更新右边。

设p[i]为第i个字符的回文半径,_max为max{p[i]+i},也就是最远可以更新的点。之后枚举的时候,如果当前点的位置小于_max,那么就用之前的信息去更新当前位置。否则p[i]=1。之后暴力向两边匹配。然后它就O(n)啦!

CODE

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 1000010
using namespace std;

char s[MAX], a[MAX << 1];

int p[MAX << 1];

inline int Manacher()
{
    int length = strlen(s);
    a[0] = ‘\\‘, a[1] = ‘$‘;
    for(int i = 1; i <= length; ++i)
        a[i << 1] = s[i - 1], a[i << 1|1] = ‘$‘;
    ++length, length <<= 1;
    int re = 0, pos = 0, _max = 0;
    for(int i = 1; i < length; ++i) {
        if(_max > i)    p[i] = min(p[(pos << 1) - i], _max - i);
        else    p[i] = 1;
        while(a[i - p[i]] == a[i + p[i]])   ++p[i];
        if(_max < p[i] + i)
            _max = p[i] + i, pos = i;
        re = max(re, p[i]);
    }
    return re - 1;
}

int main()
{
    int T = 0;
    while(scanf("%s",s), strcmp(s, "END"))
        printf("Case %d: %d\n", ++T, Manacher());
    return 0;
}
时间: 2024-10-29 19:09:52

POJ 3974 Palindrome Manacher的相关文章

POJ 3974 Palindrome Manacher算法题解

本题就是求最长的回文子串. 字符串超长,不过限时却是也很长的15秒,最长的限时之一题目了,如果限时短点的话,估计能过的人不多. 使用Mancher算法是可以秒杀的. 模板式的Manacher算法: #include <stdio.h> #include <vector> #include <string.h> #include <algorithm> #include <iostream> #include <string> #inc

POJ 3974 Palindrome | 马拉车模板

给一个字符串,求最长回文字串有多长 #include<cstdio> #include<algorithm> #include<cstring> #define N 1000005 using namespace std; int n,m,T,p[N*2],ans; char s[2*N],t[N]; void manacher() { int id=0,pos=0,x=0; for (int i=1;i<+n;i++) { if (pos>i) x=min

poj 3974 Palindrome

/* 裸地manachar */ #include<iostream> #include<cstdio> #include<cstring> #define maxn 1000010 using namespace std; int l,len[maxn]; char s[maxn],ss[maxn]; int manachar() { int ans=0; int id=-1,mx=-1; for(int i=1;i<=l;i++) { if(id+mx-i&g

后缀数组 POJ 3974 Palindrome &amp;&amp; URAL 1297 Palindrome

题目链接 题意:求给定的字符串的最长回文子串 分析:做法是构造一个新的字符串是原字符串+反转后的原字符串(这样方便求两边回文的后缀的最长前缀),即newS = S + '$' + revS,枚举回文串中心位置,RMQ询问LCP = min (height[rank[l]+1] to height[rank[r]]),注意的是RMQ传入参数最好是后缀的位置,因为它们在树上的顺序未知,且左边还要+1. #include <cstdio> #include <algorithm> #in

【POJ 3974】 Palindrome

[POJ 3974] Palindrome Manacher纯模板题 忘记的时候可以拿来找感觉 代码如下: #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; char str[1111111]; char nwstr[2333333]; int p[2333333]; int Manacher() { int len

POJ 1159 Palindrome 题解

本题的题意理解之后,就是求最长回文子序列 longest palindrome subsequence,这里注意子序列和子串的区别. 有两种求法,一种是直接求,相当于填矩阵右上对角阵,另一种是转化为longest common subsequence的求法. 最大难点就是要求内存不能使用二维的. 故此第一种方法是有点难度的,因为需要把二维矩阵的对角线转化为一维表记录,对好下标就好了. 第二中方法会稍微容易点,效率都是一样的O(n*n). 方法1: #include <cstdio> const

POJ 1159 Palindrome

Palindrome Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 51518   Accepted: 17733 Description A palindrome is a symmetrical string, that is, a string read identically from left to right as well as from right to left. You are to write a

POJ 1159 Palindrome &amp;&amp; HDU 1159 Common Subsequence

1.先说说杭电的1159吧! 这道题是基础动规,比较简单! 就是要你求最长的公共子序列(不要优化) 动态转移方程: dp[i+1][j+1]=(a[i]=b[i])?dp[i][j]+1:max(dp[i+1][j],dp[i][j+1]) AC代码: #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define N 520 char a[N],b[N]; in

LCS POJ 1159 Palindrome

题目传送门 1 /* 2 LCS裸题:长度减去最大相同长度就是要插入的个数 3 */ 4 #include <cstdio> 5 #include <iostream> 6 #include <cstring> 7 #include <algorithm> 8 #include <string> 9 using namespace std; 10 11 const int MAXN = 5e3 + 10; 12 const int INF = 0