luogu2408 不同子串个数
题目背景
因为NOI被虐傻了,蒟蒻的YJQ准备来学习一下字符串,于是它碰到了这样一道题:
题目描述
给你一个长为N的字符串,求不同的子串的个数
我们定义两个子串不同,当且仅当有这两个子串长度不一样 或者长度一样且有任意一位不一样。
子串的定义:原字符串中连续的一段字符组成的字符串
输入输出格式
输入格式:
第一行一个整数N
接下来一行N个字符表示给出的字符串
输出格式:
一行一个整数,表示不一样的子串个数
输入输出样例
说明
请使用64位整数来进行输出
(具体来说,C++和C选手请使用long long 类型,pascal选手请使用Int64)
由于输入文件过大,请使用 高效的读入方法(具体的,c++和c选手请不要使用cin,pascal选手不需要管)
对于30%的数据,$ N\le 1000 N≤1000 $
对于100%的数据,$ N\le 10^5 N≤10^5 $
思路 :后缀自动机模板题,考虑到每个节点都是不同的,所以我们只要ans=sigma(len[i]-len[fa[i]]) ;
也可以做dp。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 int const N=100000+3; 4 struct node{ 5 int ch[26]; 6 int len,fa; 7 node() { memset(ch,0,sizeof(ch)); len=0;} 8 }a[N<<1]; 9 int ls=1,tot=1; 10 void add(int c){ 11 int p=ls; 12 int np=ls=++tot; 13 a[np].len=a[p].len+1; 14 for(;p&&!a[p].ch[c]; p=a[p].fa) a[p].ch[c]=np; 15 if(!p) a[np].fa=1; 16 else { 17 int q=a[p].ch[c]; 18 if(a[q].len==a[p].len+1) a[np].fa=q; 19 else { 20 int nq=++tot; a[nq]=a[q]; 21 a[nq].len=a[p].len+1; 22 a[q].fa=a[np].fa=nq; 23 for(;p && a[p].ch[c]==q; p=a[p].fa) a[p].ch[c]=nq; 24 } 25 } 26 } 27 char s[N<<1]; int len; 28 int main(){ 29 scanf("%d",&len); 30 scanf("%s",s); 31 for(int i=0;s[i];i++) add(s[i]-'a'); 32 long long ans=0; 33 for(int i=1;i<=tot;i++) ans+=a[i].len-a[a[i].fa].len; 34 printf("%lld\n",ans); 35 return 0; 36 }