CF 316G3 Good Substrings——广义后缀自动机

本文介绍了一种使用后缀自动机解决特定编程竞赛问题的方法。通过对询问串和模式串一起构建后缀自动机,计算出每个字符串上的right集合大小,并检查自动机上的节点是否符合特定条件来求解。注意在计算拓扑排序后使用q[i]而非i。

题目:http://codeforces.com/contest/316/problem/G3

对询问串和模式串一起建一个后缀自动机,做出在每个串上的 right 集合大小之后枚举自动机上的每个点看看是否合法即可(合法的话,贡献是 len[ cr ] - len[ fa ])。

注意做出拓扑序后用的是 q[ i ] 而不是 i !

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int N=550005,M=15,K=30;
int n,cnt=1,len[N],fa[N],go[N][K],ep[N];
int l[M],r[M],tx[N],q[N],ct[N][M]; ll ans;
char s[N]; bool vis[N];
int cz(int p,int w,int bh)
{
  int q=go[p][w], nq=++cnt; len[nq]=len[p]+1;
  fa[nq]=fa[q]; fa[q]=nq;
  memcpy(go[nq],go[q],sizeof go[q]);
  for(;go[p][w]==q;p=fa[p])go[p][w]=nq;
  return nq;
}
int ins(int p,int w,int bh)
{
  if(go[p][w])
    {
      int q=go[p][w];
      if(len[q]==len[p]+1)return q;
      return cz(p,w,bh);
    }
  int np=++cnt; len[np]=len[p]+1;
  for(;p&&!go[p][w];p=fa[p])go[p][w]=np;
  if(!p){fa[np]=1;return np;}
  int q=go[p][w]; if(len[q]==len[p]+1)fa[np]=q;
  else fa[np]=cz(p,w,-1);
  return np;
}
void Rsort()
{
  for(int i=1;i<=cnt;i++)tx[len[i]]++;
  for(int i=2;i<=cnt;i++)tx[i]+=tx[i-1];
  for(int i=1;i<=cnt;i++)q[tx[len[i]]--]=i;
}
bool chk(int cr)
{
  for(int i=1;i<=n;i++)
    if(ct[cr][i]<l[i]||ct[cr][i]>r[i])
      return false;
  return true;
}
int main()
{
  scanf("%s",s+1); int d=strlen(s+1);
  for(int i=1,p=1;i<=d;i++)
    p=ins(p,s[i]-'a'+1,0), ct[p][0]=1;
  scanf("%d",&n);
  for(int i=1;i<=n;i++)
    {
      scanf("%s%d%d",s+1,&l[i],&r[i]);
      d=strlen(s+1);
      for(int j=1,p=1;j<=d;j++)
    p=ins(p,s[j]-'a'+1,i), ct[p][i]=1;
    }
  Rsort();
  for(int i=cnt;i;i--)
    {
      int cr=q[i], f=fa[q[i]];////q[i] not i!!!
      for(int j=0;j<=n;j++)ct[f][j]+=ct[cr][j];
    }
  for(int i=2;i<=cnt;i++)
    if(ct[i][0]&&chk(i))
      ans+=len[i]-len[fa[i]];
  printf("%lld\n",ans);
  return 0;
}

 

转载于:https://www.cnblogs.com/Narh/p/10610598.html

D. Good Substrings time limit per test2 seconds memory limit per test512 megabytes You&#39;ve got string s, consisting of small English letters. Some of the English letters are good, the rest are bad. A substring s[l...r] (1 ≤ l ≤ r ≤ |s|) of string s  =  s1s2...s|s| (where |s| is the length of string s) is string  slsl + 1...sr. The substring s[l...r] is good, if among the letters  sl, sl + 1, ..., sr there are at most k bad ones (look at the sample&#39;s explanation to understand it more clear). Your task is to find the number of distinct good substrings of the given string s. Two substrings s[x...y] and s[p...q] are considered distinct if their content is different, i.e. s[x...y] ≠ s[p...q]. Input The first line of the input is the non-empty string s, consisting of small English letters, the string&#39;s length is at most 1500 characters. The second line of the input is the string of characters "0" and "1", the length is exactly 26 characters. If the i-th character of this string equals "1", then the i-th English letter is good, otherwise it&#39;s bad. That is, the first character of this string corresponds to letter "a", the second one corresponds to letter "b" and so on. The third line of the input consists a single integer k (0 ≤ k ≤ |s|) — the maximum acceptable number of bad characters in a good substring. Output Print a single integer — the number of distinct good substrings of string s. Examples InputCopy ababab 01000000000000000000000000 1 OutputCopy 5 InputCopy acbacbacaa 00000000000000000000000000 2 OutputCopy 8 Note In the first example there are following good substrings: "a", "ab", "b", "ba", "bab". In the second example there are following good substrings: "a", "aa", "ac", "b", "ba", "c", "ca", "cb".
03-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值