zoukankan      html  css  js  c++  java
  • 【POJ】3974 Palindrome

    http://poj.org/problem?id=3974

    题意:求s的最长回文串。(|s|<=1000000)

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <iostream>
    using namespace std;
    char s[2000050]; int len[2000050], T;
    int main() {
    	while(scanf("%s", s+1), strcmp(s+1, "END")!=0) {
    		int n=strlen(s+1), ans=1;
    		for(int i=n; i; --i) s[i<<1]=s[i], s[i<<1|1]=0;
    		n=n<<1|1;
    		s[1]=0; s[0]=1; s[n+1]=2;
    		int cur=1;
    		for(int i=2; i<=n; ++i) {
    			int &now=len[i], pos=(cur<<1)-i; now=0;
    			now=min(len[pos], cur+len[cur]-i); now=max(0, now);
    			while(s[i-now-1]==s[i+now+1]) ++now;
    			if(i+now>cur+len[cur]) cur=i;
    			ans=max(ans, now);
    		}
    		printf("Case %d: %d
    ", ++T, ans);
    	}
    	return 0;
    }
    

      

    学习了一下manacher= =

    其实就是利用回文串的性质= =回文。。然后维护一个单调的东西= =

    大概就是先处理一下串,使串变成奇数(即插入特殊字符,而且一样),这样得到的回文串都是奇数(那么半径其实就是实际的长度,即s[i-半径]~s[i+半径]是回文串)

    然后从左往右扫,维护一个回文串能到达的最远的位置,中心为cur,能到达的位置为mx=s[cur+len[cur]]。那么如果i在mx前,那么i关于cur的对称点就是i'=cur*2-i。此时由于对称性,可以得到长度至少为len[i]=min(len[i'], mx-i)。然后再继续向两边拓展,且如果位置大于了mx,记得更新。

    可以证明这样是均摊$O(n)$的...

  • 相关阅读:
    c++实现执行脚本命令
    常用命令
    ssh2.cpp
    通过scp传输文件到多个主机
    启动和监控脚本
    centos 7.2 svn 安装
    SVN提交时必须填写备注信息 配置
    centos 7.2 配置mysql
    centos 7.2 配置Nginx
    js调试的时候用console.log("变量"+scrollTop+windowHeight)
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4350316.html
Copyright © 2011-2022 走看看