列表

详情


NC17380. Thinking-Bear's necklace

描述

Thinking-Bear gave a necklace to the sister who he admired in the heart. The necklace is made of the lowercase letter head-tail string.
Sister looked at the necklace and said to Thinking-Bear: "I hope it is symmetrical". Thinking-Bear decided to cut a continuous part from the original necklace, and join to form a new necklace. A necklace is symmetrical if we can cut it into a palindrome.
Thinking-Bear can use magic. He can replace one letter to another letters. The magic can be used at most twice. Thinking-Bear want to know what's the longest length of necklace he is able to capture. We assume that the length of the new necklace must be an odd number.

输入描述

The first line of the input is T(1≤ T ≤ 100), which stands for the number of test cases you need to solve.
Each test case contains a string S, indicates the necklace. (2 < |S| ≤ 100000).

输出描述

For each test case, output a number, means the longest length of symmetrical necklace he can capture.

示例1

输入:

1
abcdaaa

输出:

7

说明:

For the sample, he can replace one letter to ``abcbaaa".

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 321ms, 内存消耗: 5376K, 提交时间: 2018-08-05 16:24:49

#include<bits/stdc++.h>

using namespace std;

typedef unsigned long long ull;

const ull P = 19260817;
const int maxn = 200000 + 9;

ull H[maxn], _H[maxn], Pow[maxn];
int T, N;
string S;

ull Hash(int l, int r, ull h[]) {// [l, r)
	return h[l] - h[r] * Pow[r - l];
}

bool ok(int x, int s, int d) {
	return Hash(x + s, x + d + 1, H) == Hash(2 * N - 1 - (x - s), 2 * N - (x - d), _H);
}

int main() {
	
	cin.tie(0);
	cout.tie(0);
	ios::sync_with_stdio(0);
	
	Pow[0] = 1;
	for(int i = 1; i < maxn; i++) {
		Pow[i] = Pow[i - 1] * P;
	}
	cin >> T;
	while(T--) {	
		cin >> S;
		N = S.size();
		S.resize(2 * N);
		for(int i = 0; i < N; i++) {
			S[i + N] = S[i];
		}
		H[2 * N] = _H[2 * N] = 0;
		for(int i = 2 * N - 1; i >= 0; i--) {
			H[i] = H[i + 1] * P + S[i];
			_H[i] = _H[i + 1] * P + S[2 * N - 1 - i];
		}
		int ans = 1, n = (N - 1) / 2;
		for(int i = n; i + n < 2 * N; i++) {
			int s = 0, l = 0, r = n;
			while(l < r) {
				int m = (l + r + 1) >> 1;
				ok(i, s, m) ? l = m : r = m - 1;
			}
			if(l + 2 >= n) {
				ans = 2 * n + 1;
				break;
			}
			s = l = l + 2, r = n;
			while(l < r) {
				int m = (l + r) >> 1;
				ok(i, s, m) ? l = m + 1 : r = m;
			}
			if(l >= n) {
				ans = 2 * n + 1;
				break;
			}
			s = ++l, r = n;
			while(l < r) {
				int m = (l + r) >> 1;
				ok(i, s, m) ? l = m + 1 : r = m;
			}
			ans = max(ans, (l - !ok(i, s, l)) * 2 + 1);
		}
		cout << ans << endl;
	}
	
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 236ms, 内存消耗: 5216K, 提交时间: 2018-08-21 01:50:53

#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;

typedef unsigned long long ull;

const int maxn = 100005;
const int seed=1e9+7;

int n,m;
char str[2*maxn];
ull has[2*maxn],rhas[2*maxn],pw[2*maxn];

void init()
{
	pw[0]=1;
	for(int i=1;i<=2*maxn;++i)
	{
		pw[i]=pw[i-1]*seed;
	}
}

void init_has()
{
	for(int i=1;i<2*n;++i)
	{
		has[i]=has[i-1]*seed+(str[i]-'a'+1);
	}
	rhas[2*n+1]=0;
	for(int i=2*n;i>0;--i)
	{
		rhas[i]=rhas[i+1]*seed+(str[i]-'a'+1);
	}
}

bool check_has(int a,int b,int c)
{
	ull sum,rsum;
	rsum=rhas[b]-rhas[b+c]*pw[c];
	sum=has[a]-has[a-c]*pw[c];
	return rsum==sum;
}

int check(int a,int b,int c)
{
	int ret=0;
	for(int i=0;i<3;++i)
	{
		int l,r,mid,cnt=0;
		l=1,r=c;
		while(l<=r)
		{
			mid=(l+r)>>1;
			if(check_has(a,b,mid))
			{
				l=mid+1;
				cnt=mid;
			}
			else
			{
				r=mid-1;
			}
		}
		ret+=cnt;
		if(cnt==c)break;
		c-=cnt+1;
		a-=cnt+1;
		b+=cnt+1;
		if(c<0)break;
		if(i<2)ret++;
	}
	return ret;
}

int main()
{
	int T;
	cin>>T;
	init();
	while(T--)
	{
		cin>>str+1;
		n=strlen(str+1);
		for(int i=n+1;i<=2*n;++i)
		{
			str[i]=str[i-n];
		}
		init_has();
		int ans=1;
		for(int i=n/2+1;i+n/2<=2*n;++i)
		{
			int x=(n-1)/2;
			x=check(i-1,i+1,x);
			ans=max(ans,x*2+1);
		}
		cout<<ans<<endl;
	}
} 

上一题