其他分享
首页 > 其他分享> > [题解] Luogu P5446 [THUPC2018]绿绿和串串

[题解] Luogu P5446 [THUPC2018]绿绿和串串

作者:互联网

[题解] Luogu P5446 [THUPC2018]绿绿和串串

·题目大意

·解题思路

首先想到用 \(Manacher\) 。
由于进行翻转操作后回文串长度必定为奇数,所以不用插入字符,然后考虑什么情况下长度是可行的。

代码实现

#include <iostream>
#include <cstring>
using namespace std;
#define reg register
namespace io {
char ch[20];
template<typename T>inline void write(T x) {
  (x < 0) && (x =- x, putchar('-'));
  (x) || putchar('0');
  reg int i = 0;
  while (x) ch[i++] = x % 10 ^48, x /= 10;
  while (i) putchar(ch[--i]);
}
}//快写
#define wt io::write
const int maxN = 1000010;
char s[maxN];
int p[maxN], flag[maxN];
int n;
void work();
int main() {
  int t;
  scanf("%d", &t);
  while (t--) work();
  return 0;
}
void work() {
  for (reg int i = 1; i <= n; ++i) flag[i] = p[i] = s[i] = 0;
  n = 1; s[0] = '@';
  scanf("%s", s + 1);
  while (s[n]) ++n;
  --n;
  for (reg int i = 1, r = 0, mid = 0; i <= n; ++i) {
    if (i <= r) p[i] = min(p[mid * 2 - i], r - i + 1);
    while (s[i + p[i]] == s[i - p[i]]) ++p[i];
    if (i + p[i] - 1 >= r) r = i + p[i] - 1, mid = i;
  }//Manacher
  for (reg int i = n; i; --i) {
    if (i + p[i] - 1 == n || (flag[i + p[i] - 1] && i - p[i] + 1 == 1)) flag[i] = 1;
  }//上面说的两种情况
  for (reg int i = 1; i <= n; ++i)
    if (flag[i]) wt(i), putchar(' ');
  putchar('\n');
}

标签:绿绿,10,int,题解,THUPC2018,flag,maxN,长度,reg
来源: https://www.cnblogs.com/LitDarkness/p/15203371.html