题意:给你一个字符串和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 }
这个是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 }