• hdu5340—Three Palindromes—(Manacher算法)——回文子串


    Three Palindromes

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 1948    Accepted Submission(s): 687


    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

    题意:给出一个字符串,问能否将字符串分为三段,并且每一段的是回文串。

    思路:这题要用到manacher算法,不知道的可以看一下这篇博客:https://blog.csdn.net/dyx404514/article/details/42061017。

    首先用manacher求出以每个点为中点的回文串的半径,然后,我们可以知道,要将字符串分为三段,那第一段一定包含第一个字符,第三段一定包含最后一个字符。然后判断第一个回文串和第三个之间剩下的字符是否构成回文串就行了。

    所以,我们找到用manacher算法求出的所有回文串中,包含了第一个字符和和最后一个字符的有那些,然后两两配对,看看是否存在某一对,他们不重合,且之间剩下的字符也是回文串。

    具体操作看代码:

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<string>
      5 #include<cmath>
      6 #include<algorithm>
      7 #include<stack>
      8 #include<queue>
      9 #define eps 1e-7
     10 #define ll long long
     11 #define inf 0x3f3f3f3f
     12 #define pi 3.141592653589793238462643383279
     13 using namespace std;
     14 const int maxn = 20007;
     15 char a[maxn],s_new[maxn<<1];
     16 int s_len[maxn<<1];
     17 
     18 int Init() //manacher算法初始化(模板) 
     19 {
     20     int len = strlen(a);
     21     s_new[0] = '@';
     22     int j = 1;
     23     for(int i=0; i<len; ++i) //在每个字符左右插入'#' 
     24     {
     25         s_new[j++] = '#';
     26         s_new[j++] = a[i];
     27     }
     28     s_new[j++] = '#';
     29     s_new[j] = '';
     30     return j;
     31 }
     32 
     33 void manacher(int len) //计算以每个点为中心的回文串的半径(模板) 
     34 {
     35     int high = 0,flag = 0;
     36     for(int i=1; i<len; ++i)
     37     {
     38         if(i < high)
     39             s_len[i] = min(high-i+1 , s_len[2*flag-i]);
     40         else
     41             s_len[i] = 1;
     42         
     43         while(s_new[i + s_len[i]] == s_new[i - s_len[i]])
     44             s_len[i]++;
     45         
     46         if(i + s_len[i] - 1 > high)
     47         {
     48             high = i+ s_len[i] -1;
     49             flag = i;
     50         }
     51     }
     52     return;
     53 }
     54 
     55 bool judge(int len) //判断是否可以分为3个回文串 
     56 {
     57     int visit1[maxn<<1], visit2[maxn<<1], cnt1 = 0, cnt2 = 0; 
         //visit1用来存储所有包含第一个字符的字符串的中点下标 58 //visit2用来存储包含最后一个字符串的中点下标 59 60 for(int i=1; i<len; ++i) //遍历一遍,找到存入visit数组中 61 {//因为以 i 为中点的回文串的长度是s_len[i]-1,所以还要判断一下这个回文串长度是否为 0; 62 if(i - s_len[i] + 1 == 1 && s_len[i] - 1 > 0) 63 visit1[cnt1++] = i; 64 if(i + s_len[i] - 1 == len-1 && s_len[i] - 1 > 0) 65 visit2[cnt2++] = i; 66 } 67 bool flag = false; 68 int mid; 69 for(int i=0; i<cnt1; ++i) //for循环的嵌套用来让三段中,第一段和第三段两两配对 70 { 71 for(int j=cnt2-1; j>=0; --j) 72 { 73 if(visit1[i] + s_len[visit1[i]] - 1 < visit2[j] - s_len[visit2[j]] + 1)
              //选出的两段不能有重合,有重合表示中间没字符了 74 { 75 mid = ( (visit1[i] + s_len[visit1[i]] - 1) + (visit2[j] - s_len[visit2[j]] + 1) ) / 2;
                //然后取两段中间剩余字符的中点 76 if(mid - s_len[mid] + 1 <= visit1[i] + s_len[visit1[i]] && s_len[mid]-1 > 0)
                //判断以中点为中心的回文串是否完全覆盖了中间所有的字符 77 { 78 flag = true; //若覆盖了,则表示可以分成三段回文串 79 break; //就不需要再继续查找了 80 } 81 } 82 } 83 if(flag) break; 84 } 85 return flag; 86 } 87 88 int main() 89 { 90 int t; 91 cin>>t; 92 while(t--) 93 { 94 scanf("%s",a); 95 int len = Init(); 96 manacher(len); 97 98 bool T_or_F = judge(len); 99 if(T_or_F) 100 cout<<"Yes "; 101 else 102 cout<<"No "; 103 } 104 return 0; 105 }
  • 相关阅读:
    线段树(题集
    T3——拆分自然数
    P1309 瑞士轮
    普通母函数简单使用
    双向广度优先搜索
    秦九韶算法
    P1043-数字游戏
    网站在阿里云备案的详细全过程详细步骤
    从git拉取代码后经常出现maven窗口不见
    SpringBoot入门教程之打成war包在tomcat容器中执行
  • 原文地址:https://www.cnblogs.com/tuyang1129/p/9365428.html
Copyright © 2020-2023  润新知