bzoj3238后缀自动机-线性构造后缀树

来源:互联网 发布:淘宝酒水保证金 编辑:程序博客网 时间:2024/05/17 23:51

不懂线性构造后缀树的看这里:http://blog.csdn.net/guoshiyuan484/article/details/73658551

这个题主要就是注意他计算的是后缀,所以我们让后缀自动机主干上的点的size=1因为不管你怎么构造后缀自动机,在从原点一直连续转移到结尾点的路径上,每个点的最长串一定都是一个后缀(当然我说的是让原来的字符串反转后构造出来的自动机!)

其他就是dp的时候有一些技巧注意,具体看代码,哦还有注意用long long 


#include<iostream>#include<cstdio>#include<algorithm>#include<vector>#include<string.h>using namespace std;struct treee{ int fa,nextt[29]; long long max,size;};treee tree[2000000];vector<int>to[2000000];int tot = 2;char s[600000];void construct(char *s,int len){ int last = 1; tree[1].max = 0; for (int i = len-1; i>=0; i--) {  int temp = s[i] - 'a'; int now = tot;  tree[now].max = tree[last].max + 1; tree[tot].size = 1; int tempfa = last; last = now;  while (tempfa&&tree[tempfa].nextt[temp] == 0)tree[tempfa].nextt[temp] = now,tempfa=tree[tempfa].fa;  if (!tempfa)  {   tree[now].fa = 1;  }  else  {   int link = tree[tempfa].nextt[temp];   if (tree[link].max == tree[tempfa].max + 1)tree[now].fa = link;   else   {    int neww = ++tot; tree[neww] = tree[link]; tree[neww].size = 0; tree[neww].max = tree[tempfa].max + 1;    tree[now].fa = neww; tree[link].fa = neww;    while (tempfa&&tree[tempfa].nextt[temp] == link)tree[tempfa].nextt[temp] = neww, tempfa = tree[tempfa].fa;//由于头结点是空的,所以对于这道题而言该不该都是无所谓的。   }  }  tot++; } for (int i = tot - 1; i > 1; i--)to[tree[i].fa].push_back(i);}long long  dfs(int num,long long &ans){ for (int i = 0; i < to[num].size(); i++) {  int kk = to[num][i];  tree[num].size += dfs(kk, ans); } ans += tree[num].size*(tree[num].size - 1)*(tree[num].max-tree[tree[num].fa].max); return tree[num].size;}int main(){ scanf("%s", s); long long n = strlen(s);  long long ans=0; //long long n = 500000; construct(s, n); dfs(1, ans); long long all = n*(n - 1)*(n + 1) / 2; all -= ans; printf("%lld\n",all); return 0;}

为了好复制:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<string.h>
using namespace std;
struct treee
{
 int fa,nextt[29];
 long long max,size;
};
treee tree[2000000];
vector<int>to[2000000];
int tot = 2;
char s[600000];
void construct(char *s,int len)
{
 int last = 1; tree[1].max = 0;
 for (int i = len-1; i>=0; i--)
 {
  int temp = s[i] - 'a'; int now = tot;
  tree[now].max = tree[last].max + 1; tree[tot].size = 1; int tempfa = last; last = now;
  while (tempfa&&tree[tempfa].nextt[temp] == 0)tree[tempfa].nextt[temp] = now,tempfa=tree[tempfa].fa;
  if (!tempfa)
  {
   tree[now].fa = 1;
  }
  else
  {
   int link = tree[tempfa].nextt[temp];
   if (tree[link].max == tree[tempfa].max + 1)tree[now].fa = link;
   else
   {
    int neww = ++tot; tree[neww] = tree[link]; tree[neww].size = 0; tree[neww].max = tree[tempfa].max + 1;
    tree[now].fa = neww; tree[link].fa = neww;
    while (tempfa&&tree[tempfa].nextt[temp] == link)tree[tempfa].nextt[temp] = neww, tempfa = tree[tempfa].fa;//由于头结点是空的,所以对于这道题而言该不该都是无所谓的。
   }
  }
  tot++;
 }
 for (int i = tot - 1; i > 1; i--)to[tree[i].fa].push_back(i);
}
long long  dfs(int num,long long &ans)
{
 for (int i = 0; i < to[num].size(); i++)
 {
  int kk = to[num][i];
  tree[num].size += dfs(kk, ans);
 }
 ans += tree[num].size*(tree[num].size - 1)*(tree[num].max-tree[tree[num].fa].max);
 return tree[num].size;
}
int main()
{
 scanf("%s", s);
 long long n = strlen(s);
 long long ans=0;
 //long long n = 500000;
 construct(s, n);
 dfs(1, ans);
 long long all = n*(n - 1)*(n + 1) / 2;
 all -= ans;
 printf("%lld\n",all);
 return 0;
}

原创粉丝点击