• [国家集训队]最长双回文串


    [国家集训队]最长双回文串

    题意

    求长度(n)的串(S)的最长双回文串(T)

    (T)能分为两部分(X,Y) ((|X| geq 1,|Y| geq 1))(X,Y)都为回文串

    分析

    可以用回文自动机维护每个位置的最长回文后缀(R[i])

    那么答案就是(max(R[i] + L[i + 1]))

    (L[i])只需要翻转(S)再求一遍即可

    代码

    #include<bits/stdc++.h>
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define eps 1e-9
    #define db long double
    #define equals(a,b) fabs(a-b) < eps
    using namespace std;
    
    typedef long long ll;
    
    
    
    inline ll rd(){
    	ll x;
    	scanf("%lld",&x);
    	return x;
    }
    
    const int maxn = 1e5 + 5;
    char ss[maxn];
    int L[maxn],R[maxn];
    
    namespace pam {
    	int sz, tot, last;
    	int cnt[maxn], ch[maxn][26], len[maxn], fail[maxn];
    	int R[maxn]; //rightmost len
    	char s[maxn];
    	inline int node(int l) {
      		sz++;
      		memset(ch[sz], 0, sizeof(ch[sz]));
      		len[sz] = l;
      		fail[sz] = cnt[sz] = 0;
      		return sz;
    	}
    	inline void clear() {
      		sz = -1;
      		last = 0;
      		s[tot = 0] = '$';
      		node(0);
      		node(-1);
      		fail[0] = 1;
    	}
    	inline int getfail(int x) {
      		while (s[tot - len[x] - 1] != s[tot]) x = fail[x];
      		return x;
    	}
    	inline void insert(char c,int idx) {
      		s[++tot] = c;
      		int now = getfail(last);
      		if (!ch[now][c - 'a']) {
        		int x = node(len[now] + 2);
        		fail[x] = ch[getfail(fail[now])][c - 'a'];
      	 	 	ch[now][c - 'a'] = x;
      			R[idx] = len[now] + 2;
    		}
    		else R[idx] = len[now] + 2;
      		last = ch[now][c - 'a'];
      		cnt[last]++;
    	}
    }
    
    int main(){
    	scanf("%s",ss + 1);
    	int len = strlen(ss + 1);
    	pam::clear();
    	for(int i = 1;i <= len;i++)
    		pam::insert(ss[i],i);
    	int ans = 0;
    	for(int i = 1;i <= len;i++){
    		R[i] = pam::R[i];
    	}
    	pam::clear();
    	reverse(ss + 1,ss + len + 1);
    	for(int i = 1;i <= len;i++)
    		pam::insert(ss[i],i);
    	for(int i = 1;i <= len;i++){
    		L[len - i + 1] = pam::R[i];
    	}
    	for(int i = 1;i < len;i++){
    		ans = max(ans,R[i] + L[i + 1]);
    	}
    	cout << ans;
    }
    
  • 相关阅读:
    C# 基于正则表达式的字符串验证
    Matlab 曲线绘制之线型和颜色 示例
    色彩学基础知识
    Matlab 常用绘图指令(二维图形)
    让机器教人学习更有效:Becoming the Expert
    基于直接最小二乘的椭圆拟合(Direct Least Squares Fitting of Ellipses)
    一维最大熵二值化方法
    基于模板的全自动目标检测跟踪系统的设想
    纽扣检测及其旋转角度
    指针式压力表自动读数:Auto Read the Value of Manometer
  • 原文地址:https://www.cnblogs.com/hznumqf/p/15007508.html
Copyright © 2020-2023  润新知