哇我感觉我终于掌握广义后缀自动机了
1.后缀链接保证了 被指向的点的最长串+1=起点的最小串
2.正向链接相当于将起点代表的串的集合加一个字符然后转移到目标点
3.然后还要分连续转移和不连续转移,分点的时候就相当于把原来的串分出来然后凑成连续的转移
这题不要照着hiho上的题解写,慢的要死,而且编程复杂度也是刚刚的。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;
const int mod = 1000000007;
typedef long long ll;
struct treee
{
int son[11]; ll value; int maxx;
int fa;
};
treee tree[4000000];
int root=1,diantot=2;
char s[1000020];
void getstruct(char *s, int tot)
{
int temp = root; tree[root].maxx = 1;
for (int i = 0; i < tot; i++)
{
int kind = s[i] - '0';
if (tree[temp].son[kind])
{
if (tree[tree[temp].son[kind]].maxx == tree[temp].maxx + 1)//这是连续转移就相当于是原串了
{
temp = tree[temp].son[kind];
continue;
}
else
{
int changeson = tree[temp].son[kind];//因为不是连续转移所以,新串不与原串重合那么我们要把有用的集合分出来
tree[diantot] = tree[changeson]; tree[diantot].value = 0; tree[diantot].maxx = tree[temp].maxx + 1;
tree[changeson].fa = diantot;
while (temp&&tree[temp].son[kind] == changeson)
tree[temp].son[kind] = diantot,
tree[diantot].value += (tree[temp].value * 10 + (tree[temp].maxx-tree[tree[temp].fa].maxx)*kind),
tree[diantot].value%=mod,temp=tree[temp].fa;
tree[changeson].value -= tree[diantot].value; tree[changeson].value = (tree[changeson].value + mod) % mod;
temp = diantot++;
}
}
else
{//这一部分和普通后缀自动机一样
int last = diantot;
tree[last].maxx = tree[temp].maxx + 1;
while (temp&&tree[temp].son[kind] == 0)tree[temp].son[kind] = last,
tree[last].value += (tree[temp].value * 10 + (tree[temp].maxx - tree[tree[temp].fa].maxx)*kind), tree[diantot].value %= mod,
temp = tree[temp].fa;
if (temp)
{
if (tree[temp].maxx == tree[tree[temp].son[kind]].maxx - 1)tree[last].fa = tree[temp].son[kind];
else
{
int cson = tree[temp].son[kind];
diantot++; int newson = diantot;
tree[newson] = tree[cson]; tree[newson].maxx = tree[temp].maxx + 1; tree[newson].value = 0;
tree[cson].fa = newson; tree[last].fa = newson;
while (temp&&tree[temp].son[kind] == cson)tree[temp].son[kind] = newson,
tree[newson].value += (tree[temp].value * 10 + (tree[temp].maxx - tree[tree[temp].fa].maxx)*kind),
tree[newson].value %= mod,temp=tree[temp].fa;
tree[cson].value -= tree[newson].value; tree[cson].value = (tree[cson].value + mod) % mod;
}
}
else
tree[diantot].fa = root;
diantot++; temp = last;
}
}
}
int n;
int main()
{
scanf("%d", &n);
while (n--)
{
scanf("%s", s); int len = strlen(s);
getstruct(s, len);
}
ll ans = 0;
for (int i = diantot - 1; i > 1; i--)
{
ans += tree[i].value;
ans %= mod;
}
ans = (ans + mod) % mod;
printf("%lld\n", ans);
return 0;
}