hdu 4622 Reincarnation trie树+树状数组/dp

题意:给你一个字符串和m个询问,问你l,r这个区间内出现过多少字串。

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

网上也有用后缀数组搞得、

思路(虎哥):用字典树把每一个字符串对应成一个整数 相同的字符串对应到相同的整数上

把所用的串对应的整数放在一个数组里 比如书字符串s[l...r]对应的整数是 k

那么二维数组 [l][r] 就等于k

假设一个对应好的二维数组  左下角是原点

3     4     5     2

2     3     4     0

1     6     0     0

2     0     0     0

这样求解 从l到r的不同字符串的个数 其实就是求 从[l][r] 到右下角所在的矩阵所包含不同整数的个数(不包括0)

这里需要一定的去重处理 处理后是

-1    0    1     1

0     1    1     0

1     1    0     0

1     0    0     0

然后一边dp就可以求出所有答案(因为是求一个矩形矩阵,所以我用了一个二维树状数组做的,感觉好慢- -。)

注意常用的next[26]写法的字典树有可能超内存 要优化

代码:

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <stdlib.h>
  6 #include <vector>
  7 #include <queue>
  8 #define loop(s,i,n) for(i = s;i < n;i++)
  9 #define cl(a,b) memset(a,b,sizeof(a))
 10 #define lowbit(x) x&-x
 11 using namespace std;
 12 
 13 const int maxm = 2000000;
 14 const int maxn = 2007;
 15 
 16 int head[maxm];
 17 
 18 struct node
 19 {
 20     int next,v;
 21 }g[maxm];
 22 
 23 int cnt;
 24 int c[maxn][maxn];
 25 int pos[maxm];
 26 char s[maxn];
 27 int len;
 28 void add(int a,int b,int val)
 29 {
 30     int i,j;
 31     for(i = a;i <= len;i += lowbit(i))
 32     {
 33         for(j = b;j <= len;j += lowbit(j))
 34         c[i][j] += val;
 35     }
 36 }
 37 
 38 int sum(int a,int b)
 39 {
 40     int res = 0;
 41     int i,j;
 42     for(i = a;i > 0;i -= lowbit(i))
 43     {
 44         for(j = b;j > 0;j -= lowbit(j))
 45         res+=c[i][j];
 46     }
 47     return res;
 48 }
 49 void insert(int &u,int key)
 50 {
 51     int i;
 52     for(i = head[u];i != -1;i = g[i].next)
 53     {
 54         int v;
 55         v = g[i].v;
 56         if(v == key)
 57         {
 58             u = i;
 59             return ;
 60         }
 61     }
 62     cnt++;
 63     g[cnt].next = head[u];
 64     g[cnt].v = key;
 65     head[u] = cnt;
 66     u = cnt;
 67     return ;
 68 }
 69 int main()
 70 {
 71     int t;
 72     //freopen("out.txt","w",stdout);
 73     scanf("%d",&t);
 74     while(t--)
 75     {
 76         scanf("%s",s);
 77         len = strlen(s);
 78         cl(c,0);
 79         cl(pos,-1);
 80         cl(head,-1);
 81         int j,i,loc;
 82         loc = 0;
 83         cnt = 0;
 84         loop(0,j,len)
 85         {
 86             loc = 0;
 87             for(i = j;i >= 0;--i)
 88             {
 89                 int key = s[i]-'a';
 90 
 91                 insert(loc,key);
 92 
 93                 if(pos[loc] == -1)
 94                 {
 95                     add(i+1,j+1,1);
 96                     pos[loc] = i+1;
 97                 }
 98                 else if(pos[loc] < (i+1))
 99                 {
100                     add(i+1,j+1,1);
101                     add(pos[loc],j+1,-1);
102                     pos[loc] = i+1;
103                 }
104             }
105         }
106         int m,l,r;
107         scanf("%d",&m);
108         while(m--)
109         {
110             scanf("%d %d",&l,&r);
111             printf("%d
",sum(l-1,0)+sum(len,r)-sum(l-1,r)-sum(len,0));
112         }
113 
114     }
115     return 0;
116 }
View Code

这个是dp的。

 1 #include<stdio.h>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<string.h>
 5 using namespace std;
 6 struct list
 7 {
 8     int next;
 9     int v;
10 }g[2000001];
11 int head[2000001];
12 int vis[2000001];
13 int ct;
14 char str[3001];
15 int c[2001][2001];
16 void add(int x,int &u)
17 {
18     for(int i=head[u];i!=-1;i=g[i].next)
19     {
20         if(x==g[i].v)
21         {
22             u=i;return ;
23         }
24     }
25     g[ct].next=head[u];
26     g[ct].v=x;
27     head[u]=ct;
28     u=ct++;
29 }
30 int main()
31 {
32     int n,p;
33     int T,i,j;
34     scanf("%d%*c",&T);
35     while(T--)
36     {
37         ct=1;
38         memset(head,-1,sizeof(head));
39         memset(vis,-1,sizeof(vis));
40         memset(c,0,sizeof(c));
41         gets(str);
42         n=strlen(str);
43         for(j=0;j<n;j++)
44         {
45             p=0;
46             for(i=j;i>=0;i--)
47             {
48                 add(str[i],p);
49                 if(vis[p]==-1)
50                 {
51                     vis[p]=i;
52                     c[i][j]++;
53                 }
54                 else if(vis[p]<i)
55                 {
56                     c[i][j]++;
57                     c[vis[p]][j]--;
58                     vis[p]=i;
59                 }
60             }
61         }
62     //    for(j=1;j<n;j++)c[0][j]+=c[0][j-1];
63         for(j=1;j<n;j++)
64         {
65             for(i=j;i>=0;i--)
66             {
67                 c[i][j]+=c[i+1][j]+c[i][j-1]-c[i+1][j-1];
68             }
69         }
70         int q,a,b;
71         cin>>q;
72         while(q--)
73         {
74             scanf("%d%d%*c",&a,&b);
75             printf("%d
",c[a-1][b-1]);
76         }
77     }
78     return 0;
79 }
View Code
原文地址:https://www.cnblogs.com/0803yijia/p/3234241.html