zoukankan      html  css  js  c++  java
  • HDU

    HDU - 3068
    Time Limit: 2000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u

     Status

    Description

    给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 
    回文就是正反读都是一样的字符串,如aba, abba等

    Input

    输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S 
    两组case之间由空行隔开(该空行不用处理) 
    字符串长度len <= 110000

    Output

    每一行一个整数x,对应一组case,表示该组case的字符串中所包含的最长回文长度. 

    Sample Input

    aaaa
    
    abab

    Sample Output

    4
    3

    Source

    题目要求求出最长回文子串,是一道manacher的模板题。

    我们先讲一下manacher,我们先处理一下字符串,把字符串处理成#a#a#这样的格式,比如abcd处理成#a#b#c#d#,这样的好处是解决了判断回文串是奇数和偶数的问题,把回文串强制变成奇数。接下来,定义一个p[]数组,p[i]代表以节点i为中心的最长回文串的半径。例如aaaa这个字符串,p[0]=p[3]=1,p[1]=p[2]=2。同时我们定义一个变量mx和id,mx代表当前判断过的回文子串最长延伸(往右)到哪里,可以理解为当前判断过的回文子串到达的最大下标。而id代表当前更新的mx值所对应的回文串的中心的下标。如果不是很清楚可以直接看下代码。剩下部分直接看代码注释吧。最好自己在纸上画一下

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    #define X first
    #define Y second
    #define clr(u,v); memset(u,v,sizeof(u));
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pii;
    const int maxn=2e5+10;//注意开两倍大小
    const int INF=0x3f3f3f3f;
    char s[maxn],str[maxn];//s为原字符串,str为处理后的字符串
    int p[maxn];//p[i]代表以i为中心的回文串的最长半径
    int len1,len2;//分别代表s的长度和str的长度
    void init()//预处理出str
    {
        len1=strlen(s);
        str[0]='$';//在首位加一个特殊字符,防止越界
        str[1]='#';
        for (int i=0;i<len1;i++)
        {
            str[2*i+2]=s[i];
            str[2*i+3]='#';
        }
        len2=len1*2+2;
        str[len2]='';//不能和首位字符一样
    }
    void manacher()
    {
        int mx=0,id=0;
        for (int i=1;i<len2;i++)
        {
            if (mx>i) //如果当前的i在mx以内,说明i为我们之前求的回文串的范围里面
         p[i]=min(p[2*id-i],mx-i);//2*id-i代表i关于id对称的下标,我们前面求出他是回文串,因此具备了对称性,而2*id-i一定小于i,我们的i是从左到右扫描的,所以p[2*id-i]一定处理出来了,所以我们可以直接用p[2*id-i]的值,但是他不能超过mx-i,因为超过mx值我们就不能保证它是回文串,所以取二者最小 else p[i]=1;//如果i不在回文串的范围内,则初始化p[i]=1; for (;str[i-p[i]]==str[i+p[i]];p[i]++);//暴力往两边匹配,找到以i为中心的最长回文串 if (mx<i+p[i])更新mx值和id值 { mx=i+p[i]; id=i; } } } int solve() { int ans=0; for (int i=1;i<len2;i++) if (ans<p[i]) ans=p[i];//找最大的p[i]就是答案 return ans-1; } int main() { while (~scanf("%s",s)) { init(); manacher(); printf("%d ",solve()); } return 0; }
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  • 相关阅读:
    Android开发之SQLite的使用方法
    【转】如何分析解决Android ANR
    error log
    33层高楼为什么27楼和28楼最贵 次顶层房价高原因揭秘
    Could not allocate CursorWindow size due to error -12 错误解决方法
    过来人讲述买房血泪史:什么样的房子不能碰
    cocos2d-x删除vs2010项目模板
    Lua学习笔记5:类及继承的实现
    Linux vsftpd服务配置具体解释
    Android_Dialog_设置Dialog窗体的大小
  • 原文地址:https://www.cnblogs.com/scaugsh/p/5964508.html
Copyright © 2011-2022 走看看