P5446

  • 由翻转可知:S[j,k]==S[k,i]

  • 因此 R 是 S 的前缀 且 R 的后缀是回文串

    • 用 Manacher 算出最大回文半径 d
  • 此外,R 也可以由多次反转得到

    • 条件是:
      • R' 经过反转后是符合R 是 S 的前缀 且 R 的后缀是回文串
      • 且 R' 本身是回文串,这使得 R' 翻转后得到 R
    # include <bits/stdc++.h>
    # define int long long
    using namespace std;
    const int N = (int)1e6 + 10;
    int t;
    int l, r, d[N];
    bool vis[N];
    char s[N];
    void Manacher(int n){
    int l = 0, r = 0;
    s[0] = '@', s[n + 1] = '#';
    for(int i = 1; i <= n; i++){
    d[i] = 0;
    if(i > r){
    while(s[i + d[i]] == s[i - d[i]]){
    d[i]++;
    }
    l = i - d[i] + 1;
    r = i + d[i] - 1;
    }else{
    int j = l + (r - i);
    if(j - d[j] >= l){
    d[i] = d[j];
    }else{
    d[i] = r - i;
    while(s[i + d[i]] == s[i - d[i]]){
    d[i]++;
    }
    l = i - d[i] + 1;
    r = i + d[i] - 1;
    }
    }
    }
    for(int i = 1; i <= n; i++){
    d[i]--;
    }
    }
    signed main(){
    // freopen("1.in", "r", stdin);
    cin >> t;
    while(t--){
    cin >> (s + 1);
    int n = strlen(s + 1);
    Manacher(n);
    for(int i = n; i >= 1; i--){
    if(i + d[i] == n){
    vis[i] = 1;
    }else if(vis[i + d[i]] == 1 && i - d[i] == 1){
    vis[i] = 1;
    }
    }
    for(int i = 1; i <= n; i++){
    if(vis[i] == 1){
    cout << i << " ";
    }
    vis[i] = 0;
    }
    cout << "\n";
    }
    }
posted on   Bubble_e  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话



点击右上角即可分享
微信分享提示