链接:https://ac.nowcoder.com/acm/contest/886/C
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
分数:2800
题目描述
Doctor has a string
s
s
s consisting of only lowercase letters. Doctor has got the set of all palindromic substrings of a string
s
s
s, denoted by the set
S
S
S. Now, he wants to choose two distinct strings
a
a
a and
b
b
b from the set
S
S
S which satisfy that the string a is
a
a
a substring of the string
b
b
b. How many different pairs (
a
a
a,
b
b
b) can Doctor choose?
输入描述:
There are multiple test cases. The first line contains an integer T ( 1 ≤ T ≤ 5 ) T(1 \leq T \leq 5) T(1≤T≤5), indicating the number of test cases. Test cases are given in the following.
Each test case consists of only one line, containing a non-empty string s s s ( 1 ≤ ∣ s ∣ ≤ 100000 1 \leq |s| \leq 100000 1≤∣s∣≤100000), consisting of only lowercase letters.
输出描述:
For each test case, output “Case #x: y” in one line (without quotes), where x indicates the case number starting from 1, and y denotes the answer to this test case.
示例1
输入
4
aaaa
abba
abacaba
abc
输出
Case #1: 6
Case #2: 4
Case #3: 14
Case #4: 0
题意:
给定一个字符串
s
s
s,设其所有本质不同的回文子串组成的集合为
S
S
S,问有多少对
(
a
,
b
)
(a,b)
(a,b)满足
(
a
,
b
∈
S
)
(a,b \in S)
(a,b∈S)且
a
a
a是
b
b
b的子串
题解:
果然对回文自动机的各个标签表示还是不够熟悉啊…
由于我们知道,如果
f
a
[
u
]
=
v
fa[u]=v
fa[u]=v那么
v
v
v就是
u
u
u的一个真子回文串。
我们从回文树的两个节点开始dfs。
那么我们对于每一个回文串
x
x
x统计所有合法的(长度大于等于1的)
f
a
[
x
]
fa[x]
fa[x],
f
a
[
f
a
[
x
]
]
fa[fa[x]]
fa[fa[x]],
f
a
[
f
a
[
f
a
[
x
]
]
]
.
.
.
.
.
fa[fa[fa[x]]].....
fa[fa[fa[x]]].....的数量
c
o
[
x
]
co[x]
co[x]和他的所有后继节点的回文串数量
b
o
[
x
]
bo[x]
bo[x]。
然后接下去进入下一个节点,进行相同的操作。
记住每个节点只能被统计一次,也只能被计算一次。
最后计算
(
∑
b
o
[
i
]
∗
c
o
[
i
]
)
−
本
质
不
同
回
文
串
总
数
(\sum bo[i]*co[i]) - 本质不同回文串总数
(∑bo[i]∗co[i])−本质不同回文串总数 即可。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN=400004;
const int D=27;
char s[MAXN];
int l;
struct PAM{
int cnt,last;
ll ans;
int fa[MAXN],len[MAXN],ch[MAXN][D],co[MAXN],bo[MAXN],vis[MAXN];
int create(int Len,int Fa){
len[cnt]=Len;
fa[cnt]=Fa;
return cnt++;
}
void CLEAR(){
memset(vis,-1,sizeof(vis));
for(int i=0;i<cnt;i++){
len[i]=0;fa[i]=0;
memset(ch[i],0,sizeof(ch[i]));
}
last=0;cnt=0;
create(0,1);
create(-1,0);
ans=0;
}
int getfail(int p,int n){
for(;s[n-len[p]-1]!=s[n];p=fa[p]);
return p;
}
int add(int c,int pos){
int p=getfail(last,pos);
if(!ch[p][c]){
ch[p][c]=create(len[p]+2,ch[getfail(fa[p],pos)][c]);
}
last=ch[p][c];
return last;
}
int dfs(int x){
bo[x]=1;
co[x]=0;
for(int i=x;i>1;i=fa[i]){
if(vis[i]!=-1)break;
vis[i]=x;
co[x]++;
}
for(int i=0;i<26;i++){
if(ch[x][i]){
bo[x]+=dfs(ch[x][i]);
}
}
for(int i=x;i>1;i=fa[i]){
if(vis[i]!=x)break;
vis[i]=-1;
}
return bo[x];
}
ll getans(){
ans=0;
dfs(1);
dfs(0);
for(int i=2;i<cnt;i++){
ans+=1LL*bo[i]*co[i];
}
return ans-cnt+2;
}
}pam;
int w33ha(int CASE){
scanf("%s",s+1);
l=strlen(s+1);
pam.CLEAR();
for(int i=1;i<=l;i++){
pam.add(s[i]-'a',i);
}
printf("Case #%d: %lld\n",CASE,pam.getans());
return 0;
}
int main(){
int T;scanf("%d",&T);
for(int i=1;i<=T;i++)w33ha(i);
return 0;
}