题目链接: string
题目描述
We call a,ba,ba,b non-equivalent if and only if a≠ba \neq ba=b and a≠rev(b)a \neq rev(b)a=rev(b), where rev(s)rev(s)rev(s) refers to the string obtained by reversing characters of sss, for example rev(abca)=acbarev(abca)=acbarev(abca)=acba.
There is a string sss consisted of lower-case letters. You need to find some substrings of sss so that any two of them are non-equivalent. Find out what's the largest number of substrings you can choose.
输入描述:
A line containing a string sss of lower-case letters.
输出描述:
A positive integer - the largest possible number of substrings of sss that are non-equivalent.
输入
abac
输出
8
说明
The set of following substrings is such a choice: abac,b,a,ab,aba,bac,ac,cabac,b,a,ab,aba,bac,ac,cabac,b,a,ab,aba,bac,ac,c.
备注:
1≤∣s∣≤2×1051 \leq |s|\leq 2 \times 10^51≤∣s∣≤2×105, sss is consisted of lower-case letters.
题意:
找出一个字符串的所有子串中 每个子串本身以及反转之后 两两之间各不相同的子串的个数
分析:
通过pam得到所有子串中不同的回文串个数s1-2;(一个空串)
构建新的字符串 原串+(特殊符号)+反转串 通过sam得到不同的子串个数s2-2;(两个空串)
ans=(s1+s2-3)/2;
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=8e5+7;
char s[maxn];
struct SAM{
int next[maxn][27],fa[maxn],len[maxn];
int root,tot,last; ll dp[maxn];
void init(){
tot=0;
memset(dp,-1,sizeof(dp));
last=root=newnode(0);
}
int newnode(int l){
fa[tot]=-1;
for(int i=0;i<27;++i) next[tot][i]=-1;
len[tot++]=l; return tot-1;
}
void insert(int x){
int p=last; int cur=newnode(len[p]+1);
while(p!=-1&&next[p][x]==-1){
next[p][x]=cur; p=fa[p];
}
if(p==-1) fa[cur]=root;
else{
int q=next[p][x];
if(len[q]==len[p]+1) fa[cur]=q;
else{
int tmp=newnode(len[p]+1);
memcpy(next[tmp],next[q],sizeof(next[q]));
fa[tmp]=fa[q]; fa[q]=fa[cur]=tmp;
while(p!=-1&&next[p][x]==q){
next[p][x]=tmp; p=fa[p];
}
}
}
last=cur;
}
ll dfs(int u){
if(dp[u]!=-1) return dp[u];
ll res=1;
for(int i=0;i<26;++i){
if(next[u][i]==-1) continue;
res+=dfs(next[u][i]);
}
return dp[u]=res;
}
}sam;
struct PAM{
int next[maxn][26],fail[maxn],len[maxn];
int txt[maxn];
int tot,root0,root1,last,size;
void init(){
last=tot=size=0; txt[size]=-1;
root0=newnode(0); root1=newnode(-1);
fail[root0]=1; fail[root1]=0;
}
int newnode(int l){
len[tot]=l;
memset(next[tot],0,sizeof(next[tot]));
tot++; return tot-1;
}
int getfail(int x){
while(txt[size-len[x]-1]!=txt[size]) x=fail[x];
return x;
}
void insert(int c){
txt[++size]=c; int now=getfail(last);
if(!next[now][c]){
int tmp=newnode(len[now]+2);
fail[tmp]=next[getfail(fail[now])][c];
next[now][c]=tmp;
}
last=next[now][c];
}
}pam;
int main()
{
scanf("%s",s);
sam.init();pam.init();
int st=strlen(s);
for (int i=0;i<st;i++)
{
sam.insert(s[i]-'a');
pam.insert(s[i]-'a');
}
sam.insert(26);
for (int i=st-1;i>=0;i--) sam.insert(s[i]-'a');
printf("%lld\n",(sam.dfs(sam.root)+pam.tot-2-1)/2);
return 0;
}
其实我就是来贴板子的 贴完了 我走了