正题
题目链接:https://www.luogu.com.cn/problem/P3449
题目大意
nnn个回文串,求有多少对回文串有序拼接可以形成一个新的回文串。
解题思路
结论:当两个回文串的最短循环节相同时两个拼接起来就是一个新的回文串。
这里感性证明一下:
- 若两个回文串的最短循环节相同,那么这个循环节一定也是个回文串,那么若干个相同的回文串拼接那么这也一定是个回文串,所以这是充分条件。
- 若两个回文串的最短循环节不同,那么头尾的第一个循环节之中必定有一个位置不同,所以这是必要条件。
- 感性理解
所以我们用字符串hashhashhash判断即可。
codecodecode
#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);
}