The original problem can be translated as: Given the K string, how many times it appears as a substring in the L-r string
Defines a suffix (nonsense) of a prefix of a substring to a string
is equivalent to inserting a string into the trie, where each passing node and its upward fail chain are substrings of that string
And because for a fail chain, U-up can access to v current only if u is in V's Coshine
Then the original question becomes:
Inserts a l-r string into trie as described above and increments the Val value of the passed node
The weights and values of the subtree of the word node corresponding to the K string in the fail tree are obtained.
And because the query information satisfies the interval reduction, we can build the fail tree
The fail tree maintains DFS sequence with a durable segment tree complete single point modification and subtree queries
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include < Algorithm> #include <queue>using namespace std;const int maxn=500010;int n,m,sum=0;int l,r,k;int pos[maxn];int Rt[maxn];char s[maxn];queue<int>q;int h[maxn],cnt=0;int a[maxn],b[maxn],tot=0;struct edge{int to,next;} g[maxn<<1];void Add (int x,int y) {++cnt; G[cnt].to=y; g[cnt].next=h[x];h[x]=cnt;} void Get_dfs (int u) {a[u]=++tot;for (int i=h[u];i;i=g[i].next) Get_dfs (g[i].to); B[u]=tot;} struct Seg_tree{int l,r,v;} t[11000010];void Build (int &o,int l,int R) {o=++sum;if (l==r) return;int mid= (l+r) >>1;build (T[o]. L,L,MID); build (T[o]. R,MID+1,R);} void Modify (int &o,int l,int r,int p) {t[++sum]=t[o];o=sum;if (l==r) {T[o].v++;return;} int mid= (L+R) >>1;if (p<=mid) modify (T[o]. L,L,MID,P); else modify (T[o]. R,MID+1,R,P); T[o].v=t[t[o]. L].v+t[t[o]. R].V;} int ask (int o,int l,int r,int x,int y) {if (l>=x&&r<=y) return t[o].v;int mid= (l+r) >>1;if (Y<=mid) return asK (T[o]. L,l,mid,x,y); else if (X>mid) return Ask (T[o]. R,mid+1,r,x,y), else return ask (T[o]. L,l,mid,x,y) +ask (T[o]. R,mid+1,r,x,y);} struct Trie{int cnt;int t[maxn][26];int fail[maxn],fa[maxn];void init () {cnt=1;fail[0]=1;for (int i=0;i<26;++i) t[0] [I]=1;} int Insert () {int Len=strlen (s+1), int now=1;for (int i=1;i<=len;++i) {int id=s[i]-' a '; if (!t[now][id]) t[now][id]=++ Cnt,fa[t[now][id]]=now;now=t[now][id];} return now;} void Build_fail () {Q.push (1); Fail[1]=0;while (! Q.empty ()) {int U=q.front (); Q.pop (); for (int i=0;i<26;++i) {if (T[u][i]) {int k=fail[u];while (!t[k][i]) K=fail[k];fail[t[u][i]]=t[k][i];add (t[ K][i],t[u][i]); Q.push (T[u][i]);}} return;} void UPD () {build (rt[0],1,cnt), for (int i=1;i<=n;++i) {rt[i]=rt[i-1];for (int j=pos[i];j!=1;j=fa[j]) {Modify (Rt[i], 1,CNT,A[J]);}} return;}} Ac;int Main () {scanf ("%d%d", &n,&m); Ac.init (); for (int i=1;i<=n;++i) {scanf ("%s", s+1);p Os[i]=ac.insert ();} Ac.build_fail (); Get_dfs (1); AC. UPD (); for (int i=1;i<=m;++i) {scanf ("%d%d%d", &l,&r,&k);p rintf ("%d\n", ask (Rt[r],1,ac.cnt,a[pos[k]],b[pos[k]])-ask (rt[l-1],1,ac.cnt,a[pos[k]],b[pos[k]));} return 0;}
Can
Codeforces #305 E Mike and friends