1. 程式人生 > >ACM-ICPC 2018 焦作賽區網絡預賽 H題 String and Times(SAM)

ACM-ICPC 2018 焦作賽區網絡預賽 H題 String and Times(SAM)

anti multi long long topo spa lse each adding 焦作

Now you have a string consists of uppercase letters, two integers AA and BB. We call a substring wonderful substring when the times it appears in that string is between AA and BB (A \le times \le BAtimesB). 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, two integers AA and BB.

\sum length(S) \le 2 \times 10^6length(S)2×106,

1 \le A \le B \le length(S)1ABlength(S)

Output

For each test case, print the number of the wonderful substrings in a line.

樣例輸入

AAA 2 3
ABAB 2 2

樣例輸出

2
3

題目來源

ACM-ICPC 2018 焦作賽區網絡預賽

題解:SAM模板題

參考代碼:

//H  求子串出現次數在k1=<num<=k2;
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 4e5+10;
char ss[200005];
const int LetterSize = 26;

int tot, last,ch[MAXN][LetterSize],fa[MAXN],len[MAXN];
int sum[MAXN],tp[MAXN],cnt[MAXN]; 

void init()
{
    last = tot = 1;
    len[1] = 0;
    memset(ch,0,sizeof ch);
    memset(fa,0,sizeof fa);
    memset(cnt,0,sizeof cnt);
}

void add( int x)
{
    int p = last, np = last = ++tot;
    len[np] = len[p] + 1, cnt[last] = 1;
    while( p && !ch[p][x]) ch[p][x] = np, p = fa[p];
    if(p == 0) fa[np] = 1;
    else
    {
        int q = ch[p][x];
        if( len[q] == len[p] + 1)
            fa[np] = q;
        else
        {
            int nq = ++tot;
            memcpy( ch[nq], ch[q], sizeof ch[q]);
            len[nq] = len[p] + 1, fa[nq] = fa[q], fa[q] = fa[np] = nq;
            while( p && ch[p][x] == q)  ch[p][x] = nq, p = fa[p];
        }
    }
}

void toposort()
{
    for(int i = 1; i <= len[last]; i++)   sum[i] = 0;
    for(int i = 1; i <= tot; i++)   sum[len[i]]++;
    for(int i = 1; i <= len[last]; i++)   sum[i] += sum[i-1];
    for(int i = 1; i <= tot; i++)   tp[sum[len[i]]--] = i;
}


int main()
{

    int k1,k2;
	while(scanf("%s",ss)!=EOF)
    {
    	init();
    	scanf("%d%d",&k1,&k2);
	    long long ans=0;
        for(int i=0,len=strlen(ss);i<len;i++) add(ss[i]-‘A‘);
        toposort();
        for(int i=tot;i;i--)
        {
            int p=tp[i],fp=fa[p];
            cnt[fp]+=cnt[p];
            if(cnt[p]>=k1 && cnt[p]<=k2) ans+=len[p]-len[fp];
        }
        printf("%lld\n",ans);
    }

    return 0;
}

  

ACM-ICPC 2018 焦作賽區網絡預賽 H題 String and Times(SAM)