http://www.lydsy.com/JudgeOnline/problem.php?id=3238
就算是全局变量,也不要忘记,初始化(吐血)。
长得一副lca样,没想到是个树形dp(小丫头还有两幅面孔呢)。
看代码实现吧,不大容易口头解释,把加的和减的分开算就可以了,减去的通过倒着建sam(相当于建一棵后缀树),然后算每个len取的次数实现,注意树归中一些避免重复操作。
1 /************************************************************** 2 Problem: 3238 3 User: 137shoebills 4 Language: C++ 5 Result: Accepted 6 Time:3816 ms 7 Memory:130688 kb 8 ****************************************************************/ 9 10 #include<iostream> 11 #include<cstdio> 12 #include<algorithm> 13 #include<cstring> 14 #include<cmath> 15 #include<map> 16 using namespace std; 17 const int maxn=500010; 18 char ch1[maxn]={}; 19 int siz; 20 struct nod{ 21 int sig[26]; 22 int f,len; 23 }t[maxn*2];int tot=1,la=1; 24 void add(int z){ 25 int x=++tot;int i=la; 26 t[x].len=t[la].len+1; 27 for(;i&&!t[i].sig[z];i=t[i].f) 28 t[i].sig[z]=x; 29 if(!i)t[x].f=1; 30 else{ 31 int p=t[i].sig[z]; 32 if(t[p].len==t[i].len+1)t[x].f=p; 33 else{ 34 int y=++tot; 35 t[y]=t[p];t[y].len=t[i].len+1; 36 t[x].f=t[p].f=y; 37 for(;i&&t[i].sig[z]==p;i=t[i].f) 38 t[i].sig[z]=y; 39 } 40 } 41 la=x; 42 } 43 struct node{ 44 int y,next; 45 }e[maxn*2];int cnt=0; 46 int head[maxn*2]={}; 47 long long dp[maxn*2]={},sum=0; 48 void init(int x,int y){e[++cnt].y=y;e[cnt].next=head[x];head[x]=cnt;} 49 void dfs(int x){ 50 int y; 51 long long num=dp[x]*dp[x]; 52 for(int i=head[x];i;i=e[i].next){ 53 y=e[i].y; 54 dfs(y);dp[x]+=dp[y]; 55 num+=dp[y]*dp[y]; 56 } 57 sum+=(dp[x]*dp[x]-num)*t[x].len; 58 } 59 long long solve(){ 60 int j=1; 61 for(int i=siz;i>=1;i--){ 62 j=t[j].sig[ch1[i]-'a']; 63 dp[j]++; 64 } 65 for(int i=2;i<=tot;i++) 66 init(t[i].f,i); 67 dfs(1); 68 return sum; 69 } 70 int main(){ 71 memset(t,0,sizeof(t)); 72 scanf("%s",ch1+1);siz=strlen(ch1+1); 73 for(int i=siz;i>=1;i--)add((int)(ch1[i]-'a')); 74 long long ans=0; 75 for(int i=1;i<=siz;i++)ans+=(long long)i*(siz-1); 76 printf("%lld ",ans-solve()); 77 return 0; 78 }