zoukankan      html  css  js  c++  java
  • HDU 5340 Three Palindromes(Manacher)

    Problem Description:
    Can we divided a given string S into three nonempty palindromes?
     
    Input:
    First line contains a single integer T20 which denotes the number of test cases.

    For each test case , there is an single line contains a string S which only consist of lowercase English letters.1|s|20000
     
    Output:
    For each case, output the "Yes" or "No" in a single line.
     
    Sample Input:
    2
    abc
    abaadada
     
    Sample Output:
    Yes
    No

    题意:判断一个字符串是否能完全分成三个回文串。

    分析:一个字符串如果想要分成三个字符串,那么肯定第一个回文串的左端点肯定是第一个字符,第三个回文串的右端点肯定是最后一个字符,那么我们只需要判断中间的字符串是否是回文串就行啦。

    #include<stdio.h>
    #include<string.h>
    #include<queue>
    #include<math.h>
    #include<stdlib.h>
    #include<algorithm>
    using namespace std;
    
    const int N=1e6+10;
    const int INF=0x3f3f3f3f;
    const int MOD=1e9+7;
    
    typedef long long LL;
    
    char s[N], str[N];
    int r[N], k, left[N], right[N], L, R;
    
    void Palind()
    {
        int i, index = 0;
    
        for (i = 2; str[i] != ''; i++)
        {
            r[i] = 1;
    
            if (r[index]+index > i) r[i] = min(r[2*index-i], r[index]+index-i);
    
            while (str[i+r[i]] == str[i-r[i]]) r[i]++;
    
            if (r[i]+i > r[index]+index) index = i;
    
            if (r[i] == 1) continue; ///半径是1的肯定是‘#’,不能统计
            if (i-r[i] == 0) left[L++] = 2*r[i]-1; ///left保存每个左端点是第一个字符的回文串的直径
            if (i+r[i] == k) right[R++] = 2*r[i]-1; ///right保存每个右端点是最后一个字符的回文串的直径
        }
    }
    
    int main ()
    {
        int T, i, j, y, x, flag, len;
    
        scanf("%d", &T);
    
        while (T--)
        {
            k = 2;
            scanf("%s", s);
    
            memset(r, 0, sizeof(r));
            memset(str, 0, sizeof(str));
            L = R = flag = 0;
    
            str[0] = '$';
            str[1] = '#';
    
            for (i = 0; s[i] != ''; i++)
            {
                str[k++] = s[i];
                str[k++] = '#';
            }
            str[k] = '';
    
            Palind();
    
            for (i = 0; i < L; i++)
            {
                for (j = 0; j < R; j++)
                {
                    y = k-right[j]; ///计算右端点是最后一个字符的回文串的左端点
                    if (left[i] >= y) continue; ///如果左端点是第一个字符的回文串的右端点与右端点是最后一个字符的回文串的字符重合,则跳过
    
                    len = y-left[i]+1; ///计算中间字符的长度
                    x = r[len/2+left[i]]; ///计算以中间字符中心为中心的回文串的半径
                    if (x*2-1+left[i]+right[j] >= k) ///计算三个回文串的长度之和是否>=k
                    {
                        flag = 1;
                        break;
                    }
                }
    
                if (flag == 1) break;
            }
    
            if (flag == 1) printf("Yes
    ");
            else printf("No
    ");
        }
    
        return 0;
    }
  • 相关阅读:
    JS中offsetTop、clientTop、scrollTop、offsetTop各属性介绍
    在MOSS中使用无刷新的日历日程控件
    VCalendar不错的开源日历项目
    非常适用的Exchange 2007 Web Services
    在C#中实现DateDiff功能
    Div被Select挡住的解决办法
    安装Project Server2007出现错误
    vs2005中调试js(转)
    CrystalReports在MOSS下的新问题:来自磁盘上的图片不能显示
    关于多级审批工作流的问题描述
  • 原文地址:https://www.cnblogs.com/syhandll/p/4959417.html
Copyright © 2011-2022 走看看