hdu 4622 Reincarnation 字尾自動機,記憶化
阿新 • • 發佈:2018-12-13
題目要求處理出詢問的從i到j的子串的不同子串的數量,因為串長最大2000,所以n^2+記憶化處理出任意從i到j的不同子串數量(即每個節點的max-其父節點的max)
#include<bits/stdc++.h> #include<iostream> #define lan(a,b) memset(a,b,sizeof(a)) using namespace std; //const int MAXN = 4e5+10; //const int LetterSize = 26; // //int tot, last,ch[MAXN][LetterSize],fa[MAXN],len[MAXN]; //int ans=0; //void init() //{ // last = tot = 1; // len[1] = 0; // memset(ch,0,sizeof ch); // memset(fa,0,sizeof fa); // ans=0; //} // //int add( int x) //{ // int p = last, np = last = ++tot; // len[np] = len[p] + 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]; // } // } // ans+=len[last]-len[fa[last]]; // return ans; //} char s[2010]; int dp[2010][2010]; typedef long long ll; const int maxn = 4005; const int SIGMA_SIZE = 26; int sz, last; int g[maxn<<1][SIGMA_SIZE], pre[maxn<<1], step[maxn<<1]; int tot; void newNode(int s) { step[++sz] = s; pre[sz] = 0; memset(g[sz], 0, sizeof(g[sz])); } int idx(char ch) { return ch -'a'; } void init() { tot = 0; sz = 0, last = 1; newNode(0); } int insert(char ch) { newNode(step[last] + 1); int v = idx(ch), p = last, np = sz; while (p && !g[p][v]) { g[p][v] = np; p = pre[p]; } if (p) { int q = g[p][v]; if (step[q] == step[p] + 1) pre[np] = q; else { newNode(step[p] + 1); int nq = sz; for (int j = 0; j < SIGMA_SIZE; j++) g[nq][j] = g[q][j]; pre[nq] = pre[q]; pre[np] = pre[q] = nq; while (p && g[p][v] == q) { g[p][v] = nq; p = pre[p]; } } } else pre[np] = 1; tot += step[np] - step[pre[np]]; last = np; return tot; } int main() { int q,n,l,r; int t; scanf("%d",&t); while(t--) { lan(dp,0); scanf("%s",s); n=strlen(s); for(int i=0;i<n;i++) { init(); for(int j=i;j<n;j++) { dp[i+1][j+1]+=insert(s[j]); // cout <<i+1 << " " << j+1 << "= "<< dp[i+1][j+1] << endl; } } scanf("%d",&q); while(q--) { scanf("%d%d",&l,&r); printf("%d\n",dp[l][r]); } } return 0; }