ACM-ICPC 2018 焦作賽區網路預賽 H. String and Times—— 字尾自動機
阿新 • • 發佈:2018-12-10
Now you have a string consists of uppercase letters, two integers
AA
A and
BB
B. We call a substring wonderful substring when the times it appears in that string is between
AA
A and
BB
B (
A≤times≤BA \le times \le B
A≤times≤B). Can you calculate the number of wonderful substrings in that string?
Input
Input has multiple test cases.
For each line, there is a string
SS
S, two integers
AA
A and
BB
B.
∑length(S)≤2×106\sum length(S) \le 2 \times 10^6
∑length(S)≤2×10
6
,
1≤A≤B≤length(S)1 \le A \le B \le length(S)
1≤A≤B≤length(S)
Output
For each test case, print the number of the wonderful substrings in a line.
樣例輸入
複製
AAA 2 3
ABAB 2 2
樣例輸出
複製
2
3
題意:
給你一個串,x,y,叫你求出現次數在x,y之間的不同子串個數
題解:
字尾陣列我並不會求至少出現k次的子串QAQ,看別人的題解發現原來是字尾自動機的模板題。。。
#include<bits/stdc++.h> using namespace std; const int maxn = 2e5+1000; char s[maxn]; int len,k,n,m; char temp[5]; struct SAM{ int last,cnt,nxt[maxn*2][26],fa[maxn*2],l[maxn*2],num[maxn*2]; int ans; void init(){ last = cnt=1; memset(nxt[1],0,sizeof nxt[1]); fa[1]=l[1]=num[1]=0; ans=0; } int inline newnode(){ cnt++; memset(nxt[cnt],0,sizeof nxt[cnt]); fa[cnt]=l[cnt]=num[cnt]=0; return cnt; } void add(int c){ int p = last; int np = newnode(); last = np; l[np] =l[p]+1; while (p&&!nxt[p][c]){ nxt[p][c] = np; p = fa[p]; } if (!p){ fa[np] =1; }else{ int q = nxt[p][c]; if (l[q]==l[p]+1){ fa[np] =q; }else{ int nq = newnode(); memcpy(nxt[nq],nxt[q],sizeof nxt[q]); fa[nq] =fa[q]; num[nq] = num[q]; l[nq] = l[p]+1; fa[np] =fa[q] =nq; while (nxt[p][c]==q){ nxt[p][c]=nq; p = fa[p]; } } } int temp = last; while (temp){ if (num[temp]>=k){ break; } num[temp]++; if (num[temp]==k){ ans+=l[temp]-l[fa[temp]]; } temp = fa[temp]; } } }sam; int main(){ while(~scanf("%s",s)) { len = strlen(s); sam.init(); scanf("%d%d",&k,&m); for (int i=0;i<len;i++){ sam.add(s[i]-'A'); } int ans=sam.ans; k=m+1; sam.init(); for (int i=0;i<len;i++){ sam.add(s[i]-'A'); } printf("%d\n",ans-sam.ans); } return 0; }