字符串板刷
有 个规则,每个规则由字符串 以及整数对 构成。
如果一个字符串 在 中的出现次数在 内,就说明 满足了规则 .
如果一个字符串满足了所有 个规则,就说明它是好的。
给定一个字符串 ,问它的不同好子串数量。
这个问题有分级: 的长度在 以内,分别对应 难度.
对于长度在 以内的情况,可以对 个 串和 串都建立后缀自动机。
在 遍历所有路径(不同子串),将经过的字符分别插入到 串的后缀自动机中,即可知道 的每个子串在每个 串中出现的次数。
对于长度在 以内的情况,可以把所有字符串加上分隔符连接起来,然后统计每个节点在所有串中的出现次数,最后计数一遍就好。
困了。
时刻注意,一个节点的贡献不是1,而是它所表示的字符串数量。
有一个找了好长时间的bug,原来是因为我的分隔符设定成 ,然后爆char,然后变成负数之后RE了。
分隔符设置成一样是可以的,只要将其算入另外的字符串中。
/* LittleFall : Hello! */
#include <bits/stdc++.h>
using namespace std; using ll = long long; inline int read();
const int M = 500016, MOD = 1000000007;
int sz, lst; //后缀自动机大小,上一次插入的节点
int ch[M<<1][40], len[M<<1], link[M<<1], cnt[12][M<<1];
void extend(const char *s, int id)
{
for(int i=0; s[i]; ++i)
{
int c = s[i]-'a';
int cur = ++sz;
len[cur] = len[lst] + 1;
int p = lst;
while(!ch[p][c])
{
ch[p][c] = cur;
p = link[p];
}
if(ch[p][c] != cur)
{
int q = ch[p][c];
if(len[p] + 1 == len[q]) link[cur] = q;
else
{
int clone = ++sz;
memcpy(ch[clone], ch[q], sizeof(ch[q]));
link[clone] = link[q];
len[clone] = len[p]+1;
while(ch[p][c]==q)
{
ch[p][c] = clone;
p = link[p];
}
link[q] = link[cur] = clone;
}
}
lst = cur;
++cnt[id][cur];
}
}
void build()
{
vector<int> nodes;
for(int i=1; i<=sz; ++i)
nodes.push_back(i);
sort(nodes.begin(), nodes.end(), [&](int a, int b){
return len[a]>len[b];
});
for(auto u:nodes)
for(auto cntx:cnt)
cntx[link[u]] += cntx[u];
}
char str[M];
int lef[M], rig[M];
int main(void)
{
#ifdef _LITTLEFALL_
freopen("in.txt","r",stdin);
#endif
scanf("%s", str); extend(str, 0);
lef[0] = 1, rig[0] = 50000;
int n = read();
for(int i=1; i<=n; ++i)
{
string t = "{";
extend(t.c_str(), n+1);
scanf("%s", str);
extend(str, i);
lef[i] = read(), rig[i] = read();
}
build();
int ans = 0;
for(int i=1; i<=sz; ++i)
{
int suc = 1;
for(int j=0; j<=n; ++j)
if(cnt[j][i]<lef[j] || cnt[j][i]>rig[j])
suc = 0, j=n+1;
ans += suc*(len[i]-len[link[i]]);
}
printf("%d\n",ans );
return 0;
}
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}