POJ 3974

字符串中关于回文串处理,非常经典的Manacher算法

关键思想在于,我们使用中心扩展的时候,这种回文的轴对称其实已经为我们提供了一些关于当前正在讨论的对称轴的信息。当前我们正在讨论的对称轴如果恰好位于我们保存的一个全局回文串中,我们可以利用镜像对称(当前对称轴关于全局回文串中心的对称点)帮助我们获得一部分信息(对称点的回文串超出或者紧邻全局回文串边界,我们可以在原先边界基础上继续使用朴素方法),乃至全部信息(对称点的回文串恰巧包含在全局回文串中)

代码当时因为位运算的&下意识用成&&,之后对于这类细节还是要慎重

#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <stack>
#include <cstdio>
#include <cstring>
using namespace std;

const int maxl= 1e6+5;
const int maxp= maxl<<1;

char s[maxl];
int p[maxp];

inline char SS(int x, int l)
{
	char c;
	if (x< 1){
		c= '^';
	}
	else if (x> l){
		c= '$';
	}
	else{
		c=  x & 1 ? '#' : s[x>>1];
	}

	return c;
}
int Man(int l)
{	
	l<<= 1;
	++l;
	memset(p, 0, sizeof(p));
	int R= -1, mid= 0;
	int ans= -1;

	for (int i= 1; i<= l; ++i){
		if (i< R){
			int mir= p[(mid<<1)-i];
			if (mir< R-i){
				p[i]= mir;
			}
			else{
				int j;
				for (j= '#'== SS(R, l) ? R : R+1; SS(1+j, l) == SS((i<<1)-j-1, l); j+= 2){
				}

				if (j> R){
					R= j;
					mid= i;
				}
				p[i]= R-i;
			}
		}
		else{
			int j;
			for (j= '#'== SS(i, l) ? i : i+1; SS(1+j, l) == SS((i<<1)-j-1, l); ++j){
			}
			R= j;
			mid= i;
			p[i]= R-i;
		}
		if (p[i]> ans){
			ans= p[i];
		}
	}

	return ans;
}

int main()
{
	int kase= 0;
	while (~scanf(" %s", s+1) && (0!= strncmp("END", s+1, 3))){
		printf("Case %d: %d\n", ++kase, Man(strlen(s+1)));
	}

	return 0;
}
posted @ 2021-03-30 10:55  IdiotNe  阅读(36)  评论(0编辑  收藏  举报