博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj3238 [Ahoi2013]差异
阅读量:5107 次
发布时间:2019-06-13

本文共 2721 字,大约阅读时间需要 9 分钟。

地址:

题目:

3238: [Ahoi2013]差异

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 3367  Solved: 1532
[][][]

Description

Input

一行,一个字符串S

Output

 

一行,一个整数,表示所求值

Sample Input

cacao

Sample Output

54

HINT

2<=N<=500000,S由小写英文字母组成

 

思路:

  很明显前面的len[i]+len[j]是不变的,所以可以直接求出,对于后面的有俩种做法:

  后缀自动机做法:

   我们知道沿parent树往上走是不断取后缀,也就是不断删首字母。

   所以如果把字符串反转,然后沿parent树往上走则是对前缀不断取前缀的过程,也就是不断删尾字母。

   这时parent树就成lcp树,树上每个状态都是一些子串的lcp,所以树dp一下即可。

   这个树dp部分有点巧妙,学习别人的,要我写会写成dfs的形式。

sam做法:

1 /************************************************************** 2     Problem: 3238 3     User: weeping 4     Language: C++ 5     Result: Accepted 6     Time:3356 ms 7     Memory:122876 kb 8 ****************************************************************/ 9  10 #include 
11 12 using namespace std;13 14 struct SAM15 {16 static const int MAXN = 500002<<1;//大小为字符串长度两倍17 static const int LetterSize = 26;18 19 int tot, last, ch[MAXN][LetterSize], fa[MAXN], len[MAXN];20 int sum[MAXN], tp[MAXN], cnt[MAXN]; //sum,tp用于拓扑排序,tp为排序后的数组21 22 void init( void)23 {24 last = tot = 1;25 len[1] = 0;26 memset(ch,0,sizeof ch);27 memset(fa,0,sizeof fa);28 memset(cnt,0,sizeof cnt);29 }30 31 void add( int x)32 {33 int p = last, np = last = ++tot;34 len[np] = len[p] + 1, cnt[last] = 1;35 while( p && !ch[p][x]) ch[p][x] = np, p = fa[p];36 if( p == 0)37 fa[np] = 1;38 else39 {40 int q = ch[p][x];41 if( len[q] == len[p] + 1)42 fa[np] = q;43 else44 {45 int nq = ++tot;46 memcpy( ch[nq], ch[q], sizeof ch[q]);47 len[nq] = len[p] + 1, fa[nq] = fa[q], fa[q] = fa[np] = nq;48 while( p && ch[p][x] == q) ch[p][x] = nq, p = fa[p];49 }50 }51 }52 53 void toposort( void)54 {55 for(int i = 1; i <= len[last]; i++) sum[i] = 0;56 for(int i = 1; i <= tot; i++) sum[len[i]]++;57 for(int i = 1; i <= len[last]; i++) sum[i] += sum[i-1];58 for(int i = 1; i <= tot; i++) tp[sum[len[i]]--] = i;59 }60 61 void work(void)62 {63 toposort();64 long long ans=1LL*len[last]*(len[last]+1)*(len[last]-1)/2;65 for(int i=tot;i;i--)66 ans-=2LL*cnt[fa[tp[i]]]*len[fa[tp[i]]]*cnt[tp[i]],cnt[fa[tp[i]]]+=cnt[tp[i]];67 printf("%lld\n",ans);68 }69 } sam;70 71 char sa[500005];72 73 int main( void)74 {75 scanf("%s",sa);76 sam.init();77 for(int i=strlen(sa)-1;i>-1;i--) sam.add(sa[i]-'a');78 sam.work();79 return 0;80 }

 

转载于:https://www.cnblogs.com/weeping/p/7527626.html

你可能感兴趣的文章
JavaSE编程基础5
查看>>
分解CString的函数AfxExtractSubString
查看>>
JavaSE_集合_Vector
查看>>
静态全局变量和非静态全局变量
查看>>
编写模块化插件式应用程序
查看>>
VC++ 内嵌EXE
查看>>
Python进阶-----类的静态属性(@property)
查看>>
小b和矩阵
查看>>
kernel 4.18.18 rpm 制作
查看>>
前端控制器
查看>>
【redis】基于redis实现分布式并发锁
查看>>
Handler Looper 解析
查看>>
一次艰辛的算法分析---------飘零4.0封包分析
查看>>
linux grep 命令简介
查看>>
在<canvas>上绘制img(drawImage())时需要注意的事
查看>>
switchery按钮使用
查看>>
am335x USB 驱动框架记录
查看>>
团队Alpha冲刺(十)
查看>>
会长大人的《从小麦到馒头的过程》
查看>>
USACO 4.2 Drainage Ditches
查看>>