HDU 3068 &&HDU 3294 +最长回文串*3—— manacher/扩展KMP/DP

HDU 3068 http://acm.hdu.edu.cn/showproblem.php?pid=3068

HDU 3294http://acm.hdu.edu.cn/showproblem.php?pid=3294

扩展KMP:https://segmentfault.com/a/1190000008663857

感觉DP相对实现起来更简洁一些,很容易想到,可以用bool dp[i][j]:表示从i到j是否为回文串,然后最长长度用一个变量记录就好

如果dp[i][j]为回文串,那么dp[i+1][j-1]必为回文串且s[i]==s[j],所以可以得到递推关系

if(dp[i+1]][j-1]&&s[i]==s[j])  dp[i][j]=1;  maxlen=max(maxlen,i-j+1);

但是上述判断条件并不对……上面的条件漏掉了一个单个字符必为回文串的情况,第二个判断条件再加一个||j-i<2即可,或者最开始初始化dp数组的时候把i==j的部分赋值为true;

模板模板↓↓↓

bool  dp[n][n];
string s;
int n;
int DP() {
    memset(dp, 0, sizeof(dp));
    int maxlen = 0;
    for (int j = 0; j < s.length(); j++)
        for (int i = j; i >= 0; i--)
            if(s[i]==s[j]&&(j-i<2|| dp[i + 1][j - 1]))
            {
                dp[i][j] = 1;
                maxlen = max(maxlen, j - i + 1);
            }
    return maxlen;
}

但是……dp数组这样开就太大了……相对短一些的字符串还能用,长的就不行了……

manacher

manacher:https://segmentfault.com/a/1190000003914228#articleHeader8

HDU 3086

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAX = 110000 + 10;
char s[MAX*2];//数组要开两倍的
int rl[MAX*2];
int n,pos,maxlen,maxright;
int manacher()
{
    for (int i = n; i >= 0; i--)
    {
        s[2 * i + 2] = s[i];
        s[2 * i + 1] = ‘#‘;
    }
    s[0] = ‘*‘;
    s[n * 2 + 2] = ‘\0‘;
    //大佬的小技巧,防止数组越界
    for (int i = 2; i < 2 * n + 1; i++)
    {
        if (maxright > i)  //i在pos左边
            rl[i] = min(rl[2 * pos-i], maxright- i);//i在pos右边
        else rl[i] = 1;
        while (s[i - rl[i]] == s[i + rl [i]]) rl[i]++; //向两边扩展
        if (maxright < rl[i]+i - 1)  //更新maxright
        {
            maxright = rl[i] + i - 1; pos = i;
        }
        if (maxlen < rl[i]) maxlen = rl[i];
    }
    return maxlen-1;
}
int main()
{
    while (scanf("%s", s)!=EOF)
    {
        n = strlen(s); maxright = 0;
        pos = 0; maxlen = 0;
        printf("%d\n",manacher());
    }
    return 0;
}

HDU3298

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAX = 200000 + 10;
int rl[MAX * 2];
char s[MAX * 2],t[MAX*2], a[5];
int len, maxlen, pos, st,maxright,ed;
void manacher()
{
    s[0] = ‘*‘; s[2 * len + 2] = ‘\0‘;
    for (int i = 0; i < len; i++)
    {
        s[i * 2 + 1] = ‘#‘;
        s[i * 2 + 2] = t[i];
    }
    for (int i = 2; i < 2 * len + 2; i++)
    {
        if (i < maxright) rl[i] = min(maxright - i, rl[2 * pos - i]);
        else rl[i] = 1;
        while (s[i + rl[i]] == s[i - rl[i]]) rl[i]++;
        if (i + rl[i]-1 > maxright)
        {
            maxright = i + rl[i]-1;
            pos = i;
        }
        if (maxlen < rl[i])
        {
            maxlen = rl[i];
            st =(i-rl[i])/2;
            ed = (i + rl[i]) / 2-2;
        }
    }
    maxlen--;
}

int main()
{
    while (scanf("%s%s",a,t)!= EOF)
    {
        //getchar();
        len = strlen(t);
        for (int i = 0; i < len; i++)
        {
            int b = t[i] - a[0];
            if (b < 0) b += 26;
            t[i] = b + ‘a‘;
        }
        maxlen = 0;
        maxright = 0; pos = 0;
        st = 0; ed = 0;
        manacher();
        if (maxlen==1)printf("No solution!");
        else
        {
            printf("%d %d\n", st, ed);
            for (int i = st; i <= ed; i++)
                printf("%c",t[i] );
        }
        puts("");
    }
  return 0;
}

扩展KMP

emmmmmmm……还不太会……先放着,会了再更

时间: 2024-12-24 14:06:02

HDU 3068 &&HDU 3294 +最长回文串*3—— manacher/扩展KMP/DP的相关文章

HDU ACM 4513 吉哥系列故事——完美队形II-&gt;求最长回文串(manacher算法)

分析:该題可以通过求最长回文串的方法来解决:求最长回文串使用manacher算法,O(n)时间复杂度. 注意:while(a[i-len[i]]==a[i+len[i]] && a[i-len[i]]<=a[i-len[i]+2])这里多出的判断a[i-len[i]]<=a[i-len[i]+2]即为该題的限制从左到中保证身高不降,因在回文串的计算过程中添加了额外的字符,所以这里是i-len[i]+2而不是i-len[i]+1,以避开添加的字符. #include<ios

最长回文串(manacher算法)

1 const int LEN=110005; 2 const int N=LEN*2; 3 int p[N]; 4 char str[LEN], tmp[N]; 5 //p[i]表示以str[i]为中心的回文往右延伸的 最长长度 6 void manacher(char* str, int* p){ 7 int n=strlen(str), i, id, mx; 8 for(p[mx=id=0]=i=1; i<n; i++){ 9 p[i]=mx>i?min(p[2*id-i], mx-i+

(最长回文串 模板) 最长回文 -- hdu -- 3068

http://acm.hdu.edu.cn/showproblem.php?pid=3068 最长回文 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 12079    Accepted Submission(s): 4430 Problem Description 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长

Hdu 3294 Girls&#39; research (manacher 最长回文串)

题目链接: Hdu 3294  Girls' research 题目描述: 给出一串字符串代表暗码,暗码字符是通过明码循环移位得到的,比如给定b,就有b == a,c == b,d == c,.......,a == z. 问最长回文串所在区间,以及最长回文串所表示的明码. 解题思路: 字符串长度[1,200000],用manacher算法很轻松就搞定了. get√新技能请点击me 1 #include <cstdio> 2 #include <cstring> 3 #includ

hdu 3068 最长回文串 o(n) Manacher 算法

最长回文 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 10596    Accepted Submission(s): 3759 Problem Description 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 回文就是正反读都是一样的字符串,如aba, abba等 Input 输入有多

HDU 5371(Hotaru&#39;s problem-2次回文串)

Hotaru's problem Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2432    Accepted Submission(s): 841 Problem Description Hotaru Ichijou recently is addicated to math problems. Now she is playin

Manacher算法 O(n)求最长回文串

最长回文 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5158    Accepted Submission(s): 1755 Problem Description 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 回文就是正反读都是一样的字符串,如aba, abba等 Input 输入有多组

最长回文子串(Manacher算法模板题)&amp;&amp;对称字符串问题

manacher:可以解决最长回文问题. 算法:1.首先,将字符串的每个字符左右加入#,并在s0位置加入*(如果字符串中本身含有这些,则换成未出现过的字符),此时字符串的长度为len+len+3,即加入了len+1个#和一个*; (比如:aba变成 *#a#b#a#) 2.得到一个p数组,该数组是基于新字符串进行的. 得到p数组 :①从1~2*len遍历字符串,即从第一个#到最后一个字符(或者说*和最后一个#不用),即要得到p[1]~p[2*len]: ②遍历的过程中,定义了两个新变量,id和m

Manacher(输出最长回文串及下标)

http://acm.hdu.edu.cn/showproblem.php?pid=3294 Girls' research Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 5711    Accepted Submission(s): 2117 Problem Description One day, sailormoon girls