P3449-[POI2006]PAL-Palindromes【结论题,字符串hash】

正题

题目链接:https://www.luogu.com.cn/problem/P3449


题目大意

nn个回文串,求有多少对回文串有序拼接可以形成一个新的回文串。


解题思路

结论:当两个回文串的最短循环节相同时两个拼接起来就是一个新的回文串。

这里感性证明一下:

  1. 若两个回文串的最短循环节相同,那么这个循环节一定也是个回文串,那么若干个相同的回文串拼接那么这也一定是个回文串,所以这是充分条件。
  2. 若两个回文串的最短循环节不同,那么头尾的第一个循环节之中必定有一个位置不同,所以这是必要条件。
  3. 感性理解

所以我们用字符串hashhash判断即可。


codecode

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#define ll long long
#define ull unsigned long long
using namespace std;
const ll N=2e6+10,p=131;
ll n,l,ans;
ull pow[N],hash[N];
char s[N];
map<ull,ll> v;
ll get_hash(ll l,ll r){
	if(l>r) return 0;
	return hash[r]-hash[l-1]*pow[r-l+1];
}
int main()
{
	scanf("%lld",&n);
	pow[0]=1;
	for(ll j=1;j<=2e6;j++)
		pow[j]=pow[j-1]*p;
	for(ll i=1;i<=n;i++){
		scanf("%lld%s",&l,s+1);
		for(ll j=1;j<=l;j++)
			hash[j]=hash[j-1]*p+s[j]-'a';
		for(ll j=1;j<=l;j++)
			if((!(l%j))&&get_hash(1,l-j)==get_hash(j+1,l)){
				ll &z=v[hash[j]];
				ans+=2*z+1;z++;
				break;
			}
	}
	printf("%lld",ans);
} 
发布了891 篇原创文章 · 获赞 56 · 访问量 9万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章