Description
记S(i,j)为字符串S的第i个字母到第j个字母组成的子串。
给出一个长度为n由小写英文字母组成的字符串A。
若字符串B也由小写英文字母组成,长度为n,且对于任意1<=i< j<=n有:若A(i,j)是回文串,B(i,j)也是回文串;若A(i,j)不是回文串,B(i,j)也不是回文串。那么我们称B与A是ayq相似的。
求有多少个字符串与A ayq相似?输出答案对1000000007取模的余数。
Input
输入1行一个字符串A
Output
输出一行一个数表示所求答案
Sample Input
abcba
Sample Output
15600
HINT
对于100%的数据,n<=1000000
Source
和3103是双倍经验题
用马拉车找回文串,对于一个确定的回文子串我们可以把他当成一个相等关系,其他当成不等关系.
有相等关系的点可以用UFS合并一下,不等的连边
连完边就变成了图的染色问题
这里弦图染色不太会搞..而且发现自己在APIO2014回文串里写(chao)的黄学长的马拉车模板是问题的(Rivendell说那题能拍出错来QAQ
然后就换了一种模板姿势
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 1000010
#define P 1000000007
#define LL long long
using namespace std;
int n,newn,ans=1,top;
char ch[MAXN],c[MAXN<<1];
int f[MAXN],col[MAXN];
int p[MAXN<<1],maxn,id;
int vis[MAXN];
int find(int x) { return f[x]==x?x:f[x]=find(f[x]); }
void Union(int a,int b)
{
if (a&1) return;
a>>=1;b>>=1;
int x=find(a),y=find(b);
if (x!=y) f[x]=y;
}
struct edge
{
int to;
edge *next;
}e[MAXN<<1],*prev[MAXN];
void insert(int u,int v)
{
if (u&1||!u||!v) return;
u>>=1;v>>=1;e[++top].to=v;e[top].next=prev[u];prev[u]=&e[top];
}
int main()
{
scanf("%s",ch+1);int n=strlen(ch+1),newn=(n+1)<<1;
c[0]='&';c[1]='#';c[newn]='*';p[1]=1;
for (int i=1;i<=n;i++) f[i]=i;
for (int i=1;i<=n;i++) c[i<<1]=ch[i],c[i<<1|1]='#';
for (int i=2;i<newn;i++)
{
p[i]=maxn>i?min(p[2*id-i],maxn-i):1;
while (c[i-p[i]]==c[i+p[i]]) Union(i+p[i],i-p[i]),p[i]++;
insert(i+p[i],i-p[i]);
if (i+p[i]>maxn) maxn=i+p[i],id=i;
}
for (int x=1;x<=n;x++)
if (!col[find(x)])
{
int cnt=26;
for (edge *i=prev[x];i;i=i->next)
if (col[find(i->to)]&&vis[f[i->to]]<x) vis[f[i->to]]=x,cnt--;
ans=(int)((LL)ans*cnt%P);col[f[x]]=1;
}
cout<<ans<<endl;
}