HDU 4622 reincarnation (suffix array | suffix automata | KMP)

Source: Internet
Author: User

ReincarnationTime limit:6000/3000 MS (java/others) Memory limit:131072/65536 K (java/others)
Total submission (s): 2138 Accepted Submission (s): 732


Problem Descriptionnow You is Back,and has a task to do:
Given you a string s consist of lower-case 中文版 letters Only,denote F (s) as the number of distinct sub-string of S.
And you have some query,each time should calculate f (s[l ... R]), S[l ... R] means the sub-string of S start from L end at R.
Inputthe first line contains integer T (1<=t<=5), denote the number of the test cases.
For each test cases,the first line contains a string s (1 <= length of S <= 2000).
Denote the length of s by N.
The second line contains an integer Q (1 <= q <= 10000), denote the number of queries.
Then Q lines Follows,each lines contains the integer l, r (1 <= l <= r <= N), denote a query.
Outputfor each test cases,for query,print the answer on one line.
Sample Input
2bbaba53 4baaba53 33 41 43 55 5

Sample Output
3175813851Hint      I won ' t do anything against hash because I am nice. Of course this problem have a solution that don ' t rely on hash.

Source2013 multi-university Training Contest 3
Recommendzhuyuanchen520 | We have carefully selected several similar problems for you:5065 5064 5062 5061 5059Test Instructions:give you a string with a length of not more than 2000 lowercase letters. Then Q asks Q no more than 10000. Each query asks how many different substrings are in an interval [l,r]. Ideas:If you are counting the number of different substrings of the whole string, the problem is the template. Just follow the method in the paper. The key is to ask how many different substrings are in a range instead of the entire string. But we can't run a suffix array for every query. So Q*n*log (n) is definitely T. But this problem is still possible with a suffix array. But there is a deep understanding of the suffix array. In this paper, the method of counting the different substrings is using the suffix prefix is the substring. So for each suffix we can see how many different prefixes it can contribute to the answer. And this question our team runs the whole side of SA. Gets the entire string of the height array. Could it be treated like this? I started by l<=sa[i]<=r to determine that this is the suffix of the target string. Then only the string in this range is treated like a paper way. But it is wrong to do so. Because what you get is the whole string of SA. There may be such a situation. likeString for Abacand you ask for [1,3]The sa condition for this interval is3 A1 ABA2 babut the entire string of SA is1 Abac3 AC2 BAC4 Cso the 3 went to the back of 1. so we can't do this. We must understand the essence of the statistics of different substrings. A prefix that counts the contributions of different suffixes. Do not have to be heavy and leak. So when a string I in the [L,r] range is added to the contribution of the answer, it must be lost and all previous strings duplicated. The one with the largest LCP. On the line is ML. The answer is R-sa[i]+1-min (R-SA[I]+1,ML). See the code in detail:
#include <algorithm> #include <iostream> #include <string.h> #include <stdio.h>using namespace std;const int Inf=0x3f3f3f3f;const int maxn=2010;typedef long long Ll;char txt[maxn];int sa[maxn],t1[maxn],t2[maxn],ct[    Maxn],he[maxn],rk[maxn],n,m;void Getsa (char *st) {int i,k,p,*x=t1,*y=t2;    for (i=0; i<m; i++) ct[i]=0;    for (i=0; i<n; i++) ct[x[i]=st[i]]++;    for (I=1; i<m; i++) ct[i]+=ct[i-1];    for (i=n-1; i>=0; i--) sa[--ct[x[i]]]=i;        For (K=1,p=1, p<n; k<<=1,m=p) {for (p=0,i=n-k; i<n; i++) y[p++]=i;        for (i=0; i<n; i++) if (sa[i]>=k) y[p++]=sa[i]-k;        for (i=0; i<m; i++) ct[i]=0;        for (i=0; i<n; i++) ct[x[y[i]]]++;        for (I=1; i<m; i++) ct[i]+=ct[i-1];        for (i=n-1; i>=0; i--) sa[--ct[x[y[i]]]]=y[i]; for (Swap (x, y), P=1,x[sa[0]]=0,i=1; i<n; i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?    p-1:p++;    }}void gethe (char *st) {int i,j,k=0; For(i=0;i<n;i++) rk[sa[i]]=i;        for (i=0;i<n-1;i++) {if (k) k--;        J=SA[RK[I]-1];        while (St[i+k]==st[j+k]) k++;    He[rk[i]]=k;    }}int Main () {int t,i,q,le,ri,lcp,ml,ans,tp;    scanf ("%d", &t);        while (t--) {scanf ("%s", txt);        N=strlen (TXT) +1;        m=150;        Getsa (TXT);        Gethe (TXT);        scanf ("%d", &q);            while (q--) {scanf ("%d%d", &le,&ri);            Le--, ri--;            ans=lcp=ml=0;                for (i=1;i<n;i++) {lcp=min (lcp,he[i]);                Ml=min (ML,LCP);                    if (Sa[i]>=le&&sa[i]<=ri) {ans+=ri-sa[i]+1-min (RI-SA[I]+1,ML);                    LCP=HE[I+1];                    Tp=min (lcp,ri-sa[i]+1);                Ml=max (ML,TP);        }} printf ("%d\n", ans); }} return 0;} /*1lelwprbultllgkhhhyjchhngo115 21*/
The second method is the suffix automaton. This method is relatively simple (does not mean that the suffix automata simple). The suffix automaton took a long time to understand. The main reason to feel online in this respect less popular information. It may be that you are too weak. Suffix automata is one of the hardest algorithms I've learned to learn. I'm going to finish the live game and write a simple study note to save a teenager like me. This problem is only necessary in the suffix Automaton node to maintain a more information record to the node how many different substrings on the line. Each time you can know how many substrings have been added. Build n-th suffix automata to preprocess all the answers.See the code in detail:
#include <algorithm> #include <iostream> #include <string.h> #include <stdio.h>using namespace    std;const int Inf=0x3f3f3f3f;const int maxn=2010<<1;typedef long long ll;struct node{node *f,*ch[30];    int Len,way;        void Init () {way=0;    memset (ch,0,sizeof ch);    }}*root,*tail,sam[maxn<<1];int Tot,dp[2010][2010];char txt[maxn];void init () {tot=0;    root=tail=&sam[tot++];    root->f=null;    root->len=0;    Root->init (); Root->way=1;}    void Insert (int c) {node *p=tail,*np=&sam[tot++];    Np->init (),np->len=p->len+1;        while (P&&!p->ch[c]) {np->way+=p->way;    p->ch[c]=np,p=p->f;    } TAIL=NP;    if (!p) np->f=root;        else {if (p->ch[c]->len==p->len+1) np->f=p->ch[c];            else {node *q=p->ch[c],*nq=&sam[tot++];            *nq=*q;            nq->len=p->len+1; nq->way=0;            q->f=np->f=nq;                while (p&&p->ch[c]==q) {p->ch[c]->way-=p->way;                nq->way+=p->way;            p->ch[c]=nq,p=p->f;    }}}}int Main () {int i,j,t,len,q,le,ri;    scanf ("%d", &t);        while (t--) {scanf ("%s", txt);        Len=strlen (TXT);            for (i=0;i<len;i++) {init ();                for (j=i;j<len;j++) {Insert (txt[j]-' a ');            dp[i][j]=tail->way;        } for (j=i+1;j<len;j++) dp[i][j]+=dp[i][j-1];        } scanf ("%d", &q);            while (q--) {scanf ("%d%d", &le,&ri);        printf ("%d\n", dp[le-1][ri-1]); }} return 0;}

The third kind of thing KMP practice. Because the code hasn't been written yet. Take a hole first.

HDU 4622 reincarnation (suffix array | suffix automata | KMP)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.