Manacher(最长镜面回文串)

I - O‘My!

Gym - 101350I

Note: this is a harder version of Mirrored string I.

The gorillas have recently discovered that the image on the surface of the water is actually a reflection of themselves. So, the next thing for them to discover is mirrored strings.

A mirrored string is a palindrome string that will not change if you view it on a mirror.

Examples of mirrored strings are "MOM", "IOI" or "HUH". Therefore, mirrored strings must contain only mirrored letters {A, H, I, M, O, T, U, V, W, X, Y} and be a palindrome.

e.g. IWWI, MHHM are mirrored strings, while IWIW, TFC are not.

A palindrome is a string that is read the same forwards and backwards.

Given a string S of length N, help the gorillas by printing the length of the longest mirrored substring that can be made from string S.

A substring is a (possibly empty) string of characters that is contained in another string S. e.g. "Hell" is a substring of "Hello".

Input

The first line of input is T – the number of test cases.

Each test case contains a non-empty string S of maximum length 1000. The string contains only uppercase English letters.

Output

For each test case, output on a line a single integer -
the length of the longest mirrored substring that can be made from
string S.

Example

Input

3IOIKIOOIROQWOWMAN

Output

413思路:将镜面字母拆分出来,一个一个求最长回文串,差点因为数组重复而runtime error 没过,还好发现了
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include <stdio.h>
#include <string.h>
using namespace std;
const int N = 1000009 ;
char a[10009] , b[20009] ;
int p[20009] ;
int vis[27] ;
char c[20] = {‘A‘, ‘H‘, ‘I‘, ‘M‘, ‘O‘, ‘T‘, ‘U‘, ‘V‘, ‘W‘, ‘X‘, ‘Y‘};
char d[10009] ;

int cal(char *a , int lena)
{
        b[0] = ‘$‘;
        b[1] = ‘#‘;
        int l = 2 ;
        for(int i = 0 ; i < lena ; i++)
        {
            b[l++] = a[i];
            b[l++] = ‘#‘;
        }
        b[l] = ‘\0‘;
    //    cout << b << endl ;
        int mx = -1 ;
        int mid , i ;
        int len = 0 ;
        for(int i = 1 ; i < l ; i++)
        {
                if(mx > i)
                {
                    p[i] = min(p[mid * 2 - i] , mx - i);
                }
                else
                {
                    p[i] = 1 ;
                }
                while(b[i-p[i]] == b[i+p[i]])
                {
                     p[i]++;
                }
                if(mx < p[i] + i)
                {
                    mid = i ;
                    mx = p[i] + i ;
                }
                len = max(len , p[i] - 1);

        }
        return len ;
}

int main()
{
    for(int i = 0 ; i < 11 ; i++)
    {
        int x = c[i] - ‘A‘;
        vis[x] = 1 ;
    }
    int n ;
    scanf("%d" , &n);
    while(n--)
    {

        scanf("%s" , a);
        int lena = strlen(a);
        int ans = 0 ;
        int l = 0 ;
        for(int i = 0 ; i < lena ; i++)
        {
            if(vis[a[i] - ‘A‘])
            {
                d[l++] = a[i];
            }
            if(!vis[a[i] - ‘A‘] || i == lena - 1)
            {

                if(l >= 1)
                    ans = max(ans ,cal(d , l));
                d[l] = 0 ;
                l = 0 ;
                continue ;
            }
        }
        printf("%d\n" , ans);
    }

    return 0 ;
}

原文地址:https://www.cnblogs.com/nonames/p/11291334.html

时间: 2024-11-09 06:16:21

Manacher(最长镜面回文串)的相关文章

!HDU 5371 最长双回文串(多校7)-卡时间-(manacher+排序+set+lower_bound())

题意:给定一个有n个数字的序列,找出一个连续的子序列满足这样的条件:平均分成三段,第一段与第三段一样,第二段是第一段的倒序.求这样的子序列的最大长度.数据范围:n~100000 分析: 上面的条件抽象出来其实就是双回文串,所以题目就是求一个序列的最长双回文串. 主体做法是: 1.先用manacher算法O(n)求出每个元素的最大回文半径: 2.把每个元素看成一个圆心,那么两个点能构成双回文串必须满足的条件是他们在对方的圆内或圆上(画个示意图就理解了),所以接下来怎么利用最大回文半径呢.题解是这么

Manacher(最长递减回文串)

http://acm.hdu.edu.cn/showproblem.php?pid=4513 Problem Description 吉哥又想出了一个新的完美队形游戏! 假设有n个人按顺序站在他的面前,他们的身高分别是h[1], h[2] ... h[n],吉哥希望从中挑出一些人,让这些人形成一个新的队形,新的队形若满足以下三点要求,则就是新的完美队形: 1.挑出的人保持原队形的相对顺序不变,且必须都是在原队形中连续的: 2.左右对称,假设有m个人形成新的队形,则第1个人和第m个人身高相同,第2

2565: 最长双回文串 - BZOJ

Description 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为"abc",逆序为"cba",不相同). 输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串.Input 一行由小写英文字母组成的字符串S. Output 一行一个整数,表示最长双回文子串的长度.Sample Input baacaabbacabb Sample Output 12 HINT

【BZOJ】【2565】最长双回文串

Manacher算法 找出一个最长子串S=X+Y,且X和Y都是回文串,求最长的长度是多少…… 同时找两个串明显很难搞啊……但是我们可以先找到所有的回文串!在找回文串的同时我们可以预处理出来l[i]和r[i]分别表示从 i 这个位置开始向左/右最长的回文串有多长,那么我们枚举两个回文串的分割点更新答案即可. 1 /************************************************************** 2 Problem: 2565 3 User: Tunix

最长(大)回文串的查找(字符串中找出最长的回文串)PHP实现

首先还是先解释一下什么是回文串:就是从左到右或者从右到左读,都是同样的字符串.比如:上海自来水来自海上,bob等等. 那么什么又是找出最长回文串呢? 例如:字符串abcdefedcfggggggfc,其中efe,defed,cdefedc,gg,ggg,gggg,ggggg,gggggg,fggggggf,cfggggggfc都是回文串,左右完全一样. 这其中,有最短的gg,最长的cfggggggfc,还有其他长度的.忽略长度为1的.毕竟一个字符的都算回文了. 那么,找出最长的,就是找出这个cf

BZOJ2565:最长双回文串

2565: 最长双回文串 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2195  Solved: 1119[Submit][Status][Discuss] Description 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为"abc",逆序为"cba",不相同). 输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y都

HYSBZ 2565 最长双回文串 (回文树)

2565: 最长双回文串 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1377  Solved: 714 [Submit][Status][Discuss] Description 顺序和逆序读起来完全一样的串叫做回文串.比如acbca是回文串,而abc不是(abc的顺序为"abc",逆序为"cba",不相同). 输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y

【BZOJ2565】最长双回文串 Manacher

题解: 首先我们写一个Manacher模板.. 然后我们可以把所有回文串的信息映射到左端点上, 每个点依此维护最长右连接回文串. 然后再顺着扫一遍就出解了. 代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 101000 using namespace std; char ts[N],s[N<<1]; int n,

BZOJ 2565 最长双回文串 Hash+二分

题目大意:给定一个字符串,求一个最长的子串,该字串可以分解为两个回文子串 傻逼的我又忘了Manacher怎么写了= = 无奈Hash+二分吧 首先将字符串用分隔符倍增,然后求出以每个点为中心的最长回文半径 然后考虑两个回文串怎么合并成一个 我们发现图中以i为中心的回文串和以j为中心的回文串合并后长度恰好为(j-i)*2 能合并的前提是以两个点为中心的回文串有交点 那么对于每个j我们要求出有交点的最左侧的i 维护一个后缀min随便搞搞就可以了 #include <cstdio> #include