HDU4622 Reincarnation 后缀自动机

http://acm.hdu.edu.cn/showproblem.php?pid=4622

查询一个区间内的不同子串的个数,注意一下注释的地方就可以了。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<map>
 7 using namespace std;
 8 const int maxn=2010;
 9 char ch[maxn];
10 int siz=0;
11 struct sam{
12     int f,len;
13     int sig[26];
14 }t[maxn*2];int tot,la;
15 int loc[maxn*2]={};
16 int ans[maxn][maxn]={};
17 void add(int z){
18     int i=la;int x=++tot;
19     t[x].len=t[i].len+1;
20     for(;i&&!t[i].sig[z];i=t[i].f)
21         t[i].sig[z]=x;
22     if(!i)t[x].f=1;
23     else{
24         int p=t[i].sig[z];
25         if(t[p].len==t[i].len+1)t[x].f=p;
26         else{
27             int y=++tot;
28             t[y]=t[p];
29             loc[y]=loc[p];//注意loc的转移
30             t[y].len=t[i].len+1;
31             t[x].f=t[p].f=y;
32             for(;i&&t[i].sig[z]==p;i=t[i].f)
33                 t[i].sig[z]=y;
34         }
35     }la=x;
36 }
37 int main(){
38     int T;
39     scanf("%d",&T);
40     while(T-->0){
41         memset(ans,0,sizeof(ans));
42         scanf("%s",ch+1);siz=strlen(ch+1);
43         for(int i=1;i<=siz;i++){
44             memset(t,0,sizeof(t));tot=la=1;
45             memset(loc,0,sizeof(loc));
46             for(int j=i;j<=siz;j++){
47                 loc[tot+1]=j;
48                 add(ch[j]-'a');
49             }
50             for(int j=2;j<=tot;j++){
51                 ans[i][loc[j]]+=t[j].len-t[t[j].f].len;
52             }
53             for(int j=i+1;j<=siz;j++){
54                 ans[i][j]+=ans[i][j-1];
55             }
56         }
57         int n,l,r;
58         scanf("%d",&n);
59         for(int i=1;i<=n;i++){scanf("%d%d",&l,&r);printf("%d
",ans[l][r]);}
60     }
61     return 0;
62 }
View Code

翻以前的代码发现完全就是魔咒那道题的知识点。。。所以这里改了个更简洁的代码(妈耶我怕不是个智障哦)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<map>
 7 using namespace std;
 8 const int maxn=2010;
 9 char ch[maxn];
10 int siz=0;
11 struct sam{
12     int f,len;
13     int sig[26];
14 }t[maxn*2];int tot,la;
15 int ans[maxn][maxn]={},ans1=0;
16 int calc(int x){return t[x].len-t[t[x].f].len;}
17 void add(int z){
18     int i=la;int x=++tot;
19     t[x].len=t[i].len+1;
20     for(;i&&!t[i].sig[z];i=t[i].f)
21         t[i].sig[z]=x;
22     if(!i){t[x].f=1;ans1+=calc(x);}
23     else{
24         int p=t[i].sig[z];
25         if(t[p].len==t[i].len+1){t[x].f=p;ans1+=calc(x);}
26         else{
27             int y=++tot;
28             t[y]=t[p];
29             t[y].len=t[i].len+1;
30             ans1+=calc(y)-calc(p);
31             t[x].f=t[p].f=y;
32             ans1+=calc(p)+calc(x);
33             for(;i&&t[i].sig[z]==p;i=t[i].f)
34                 t[i].sig[z]=y;
35         }
36     }
37     la=x;
38 }
39 int main(){
40     int T;
41     scanf("%d",&T);
42     while(T-->0){
43         memset(ans,0,sizeof(ans));
44         scanf("%s",ch+1);siz=strlen(ch+1);
45         for(int i=1;i<=siz;i++){
46             memset(t,0,sizeof(t));tot=la=1;
47             ans1=0;
48             for(int j=i;j<=siz;j++){
49                 add(ch[j]-'a');
50                 ans[i][j]=ans1;
51             }
52         }
53         int n,l,r;
54         scanf("%d",&n);
55         for(int i=1;i<=n;i++){scanf("%d%d",&l,&r);printf("%d
",ans[l][r]);}
56     }
57     return 0;
58 }
View Code

原文地址:https://www.cnblogs.com/137shoebills/p/8575269.html