题目
Smart Beaver recently got interested in a new word game. The point is as follows: count the number of distinct good substrings of some string
s. To determine if a string is good or not the game uses rules. Overall there are
n rules. Each rule is described by a group of three
(p, l, r), where
p is a string and l and
r (l ≤ r) are integers. We’ll say that string
t complies with rule
(p, l, r), if the number of occurrences of string
t in string p lies between
l and r, inclusive. For example, string “ab“, complies with rules (“ab“,
1, 2) and (“aab“,
0, 1), but does not comply with rules (“cd“,
1, 2) and (“abab“,
0, 1).
A substring
s[l… r]
(1 ≤ l ≤ r ≤ |s|) of string
s = s1s2…
s|s| (|s| is a length of
s) is string slsl + 1…
sr.
Consider a number of occurrences
of string t in string
p as a number of pairs of integers l, r
(1 ≤ l ≤ r ≤ |p|) such that
p[l… r] = t.
We’ll say that string t is good if it complies with all
n rules. Smart Beaver asks you to help him to write a program that can calculate the number of distinct good substrings of string
s. Two substrings s[x…
y] and s[z… w] are cosidered to be distinct iff
s[x… y] ≠ s[z…
w].
The first line contains string
s. The second line contains integer n. Next
n lines contain the rules, one per line. Each of these lines contains a string and two integers
pi, li, ri, separated by single spaces (0 ≤ li ≤ ri ≤ |pi|).
It is guaranteed that all the given strings are non-empty and only contain lowercase English letters.
The input limits for scoring 30 points are (subproblem G1):
- 0 ≤ n ≤ 10.
- The length of string s and the maximum length of string
p is ≤ 200.
The input limits for scoring 70 points are (subproblems G1+G2):
- 0 ≤ n ≤ 10.
- The length of string s and the maximum length of string
p is ≤ 2000.
The input limits for scoring 100 points are (subproblems G1+G2+G3):
- 0 ≤ n ≤ 10.
- The length of string s and the maximum length of string
p is ≤ 50000.
Print a single integer — the number of good substrings of string
s.
题解
代码
#include#include #include #include using namespace std; #define Nil NULL typedef long long LL; const int INF=0x7ffffff/2; const int SIZEP=50010; const int LNUM=11; int M;//限制的数量 int lim_l[LNUM],lim_r[LNUM]; int match[256]={0}; class Suffix_Automaton{ public: class Node{ public: int len; Node *suflink;//后缀链接 Node *ch[26+LNUM];//转移 int sz[LNUM];//在每个模式串中出现次数 bool good;//是否对应"好"字符串 int range;//对应多少个字符串 int last;//首次出现位置 LL suf_sz;//后缀链接能到达好节点的range之和 void calc_range(void){ range=len; if(suflink!=Nil) range-=suflink->len; } void calc_good(void){ for(int i=1;i<=M;i++){ if(!(lim_l[i]<=sz[i]&&sz[i]<=lim_r[i])){ good=false; return; } } good=true; } void clear(void){ len=0; suflink=Nil; memset(ch,0,sizeof(ch)); memset(sz,0,sizeof(sz)); good=false; range=0; last=-1; suf_sz=0; } Node(){clear();} }; Node *root,*last; int n; Node *lis[1100050]; int timer; int findpos(Node *a){ if(a==Nil) return -1; for(int i=0;i len< suflink)< good< last< suf_sz< sz[i]<<" ";}cout< ch[i]!=Nil){cout<<(char)('a'+i)<<" : "< ch [i])< sz[id]=1; lis[n++]=cur; cur->len=last->len+1; if(id==0) cur->last=timer++; Node *p=last; while(p!=Nil&&p->ch[k]==Nil){ p->ch[k]=cur; p=p->suflink; } if(p==Nil) cur->suflink=root; else{ Node *q=p->ch[k]; if(p->len+1==q->len) cur->suflink=q; else{ Node *clone=new Node; lis[n++]=clone; *clone=*q; memset(clone->sz,0,sizeof(clone->sz)); clone->len=p->len+1; cur->suflink=clone; q->suflink=clone; while(p!=Nil&&p->ch[k]==q){ p->ch[k]=clone; p=p->suflink; } } } last=cur; } class cmp_len{ public: bool operator () (Node *a,Node *b){ return a->len len; } }; void prepare(void){ sort(lis,lis+n,cmp_len()); for(int i=n-1;i>=0;i--){ Node *p=lis[i]; if(p->suflink!=Nil){ for(int j=0;j<=M;j++) p->suflink->sz[j]+=p->sz[j]; p->suflink->last=max(p->suflink->last,p->last); } } for(int i=0;i calc_good(),lis[i]->calc_range(); for(int i=0;i suflink!=Nil&&p->last==p->suflink->last){ Node *q=p->suflink; p->suf_sz+=q->suf_sz; if(q->good){ p->suf_sz+=q->range; } } } } LL calc(char *s,int L){ LL ans=0; Node *p=root; int now=0; for(int i=0;i ch[k]==Nil){ p=p->suflink; now=p->len; } if(p->ch[k]!=Nil) p=p->ch[k],now++; if(p->last==i){//保证不重 ans+=p->suf_sz; if(p->good){ ans+=now; if(p->suflink!=Nil) ans-=p->suflink->len; } } } return ans; } }; Suffix_Automaton MT; char S[SIZEP]; int L; char str[SIZEP]; void build_MT(void){ memset(match,-1,sizeof(match)); for(int i=0;i<26;i++) match['a'+i]=i; for(int i=0;i<20;i++) match[i]=26+i; scanf("%s",S); scanf("%d",&M); char dlm='\0'; L=strlen(S); for(int i=0;i