1 条题解
-
0
推荐去看学习资料
友情赞助参考代码:#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; const int MAXN=310000; char S[MAXN];int slen; struct PAM { int len[MAXN],fail[MAXN],son[MAXN][26],p,n,last; //p:当前节点个数(p-2就是回文子串种类) n:字符串我们匹配了多少 last:第n个点弄进来之前的最长回文后缀节点位置 inline int newpoint(int l)//创建新的点,长度为l ,并返回节点编号 { for(int i=0;i<=25;i++)son[p][i]=0; len[p]=l; return p++; } inline void putin()//初始化:建立节点even,odd { n=p=last=0; newpoint(0); newpoint(-1); fail[0]=1;S[0]=-1;//我们弄一个不可能出现在字符域的字符,避免翻车 (我们fail要经过0才能跑到1) } int get_fail(int x) { while(S[n]!=S[n-1-len[x]])x=fail[x]; return x; } inline void add(int c) { c-='a';S[++n]=c; int FA=get_fail(last); if(son[FA][c]==0)//这里不等于0我们找到的就是一个以前出现过的子串 { int now=newpoint(len[FA]+2);//前后都加一个'c',所以我们长度是+2 fail[now]=son[get_fail(fail[FA])][c]; //这里求fail类似于AC自动机,找到父亲的fail(们)的儿子'c' son[FA][c]=now; } last=son[FA][c];//现在的最长回文后缀就是last了 } }pam; int main() { // freopen("data10.in","r",stdin); // freopen("data10.out","w",stdout); scanf("%s",S+1);slen=strlen(S+1); pam.putin(); for(int i=1;i<=slen;i++)pam.add(S[i]); printf("%d\n",pam.p-2); return 0; }
- 1
信息
- ID
- 1944
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- 递交数
- 19
- 已通过
- 5
- 上传者