• 【BZOJ2342】【SHOI2012】—双倍回文(Pam)


    传送门

    我们发现一个串和其倒置拼一起也是一个回文串
    SSRSSRSS^RSS^R也是一个回文串
    考虑维护一个half[k]half[k]指针表示和点kk相同分界点的最长的长度len[k]2le frac {len[k]}{2}的点

    发现这个也可以在构建PamPam的时候顺便维护

    然后枚举所有len[half[k]]2==len[k]len[half[k]]*2==len[k]的点取maxmax即可

    #include<bits/stdc++.h>
    using namespace std;
    #define gc getchar
    inline int read(){
    	char ch=gc();
    	int res=0,f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    #define re register
    #define pii pair<int,int>
    #define pb push_back
    #define fi first
    #define se second
    #define cs const
    #define ll long long
    const int N=500005;
    inline void chemx(int &a,int b){a<b?a=b:0;}
    inline void chemn(int &a,int b){a>b?a=b:0;}
    int ans;
    char s[N];
    namespace Pam{
    	int nxt[N][26],fail[N],len[N],half[N];
    	int tot,last;
    	inline void init(){
    		fail[0]=1,len[1]=-1,tot++;
    	}
    	inline void insert(int c,int i){
    		int p=last;
    		while(s[i-len[p]-1]!=s[i])p=fail[p];
    		if(!nxt[p][c]){
    			len[++tot]=len[p]+2;
    			int k=fail[p];
    			while(s[i-len[k]-1]!=s[i])k=fail[k];
    			fail[tot]=nxt[k][c],nxt[p][c]=tot;
    			k=half[p];
    			while(s[i]!=s[i-len[k]-1])k=fail[k];
    			k=nxt[k][c];
    			while(len[k]*2>len[tot])k=fail[k];
    			half[tot]=k;
    			if((len[tot]%4==0)&&(len[k]*2==len[tot]))chemx(ans,len[tot]);
    		}
    		last=nxt[p][c];
    	}
    }
    int main(){
    	int len=read();
    	scanf("%s",s+1),s[0]='$';
    	Pam::init();
    	for(int i=1;i<=len;i++)Pam::insert(s[i]-'a',i);
    	cout<<ans;
    }
    
  • 相关阅读:
    线段拟合(带拉格朗日乘子,HGL)
    工作到位的标准
    Git的简单使用
    位移
    java日期格式化(util包下转成sql包下)
    java中继承的概念
    工作流驳回到指定连线节点上
    年终个人总结
    实现多条件查询 匹配数据库字段中多个数据
    activiti和SSH项目做整合
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328776.html
Copyright © 2020-2023  润新知